Skip to content

Commit c5e4509

Browse files
committed
reconfigurator execution to populate/destroy records
1 parent 875d8e6 commit c5e4509

File tree

4 files changed

+141
-3
lines changed

4 files changed

+141
-3
lines changed

nexus/db-queries/src/db/datastore/db_metadata.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
//! [`DataStore`] methods on Database Metadata.
66
77
use super::{DataStore, DbConnection, IdentityCheckPolicy};
8+
use crate::authz;
9+
use crate::context::OpContext;
10+
811
use anyhow::{Context, bail, ensure};
912
use async_bb8_diesel::{AsyncRunQueryDsl, AsyncSimpleConnection};
1013
use chrono::Utc;
1114
use diesel::prelude::*;
15+
use futures::FutureExt;
1216
use nexus_db_errors::ErrorHandler;
1317
use nexus_db_errors::OptionalError;
1418
use nexus_db_errors::public_error_from_diesel;
@@ -19,7 +23,9 @@ use nexus_db_model::DbMetadataNexusState;
1923
use nexus_db_model::EARLIEST_SUPPORTED_VERSION;
2024
use nexus_db_model::SchemaUpgradeStep;
2125
use nexus_db_model::SchemaVersion;
26+
use nexus_types::deployment::BlueprintZoneDisposition;
2227
use omicron_common::api::external::Error;
28+
use omicron_uuid_kinds::GenericUuid;
2329
use omicron_uuid_kinds::OmicronZoneUuid;
2430
use semver::Version;
2531
use slog::{Logger, error, info, o};
@@ -701,6 +707,80 @@ impl DataStore {
701707
Ok(exists)
702708
}
703709

710+
/// Deletes the "db_metadata_nexus" record for a Nexus ID, if it exists.
711+
pub async fn database_nexus_access_delete(
712+
&self,
713+
opctx: &OpContext,
714+
nexus_id: OmicronZoneUuid,
715+
) -> Result<(), Error> {
716+
use nexus_db_schema::schema::db_metadata_nexus::dsl;
717+
718+
opctx.authorize(authz::Action::Modify, &authz::FLEET).await?;
719+
let conn = &*self.pool_connection_authorized(&opctx).await?;
720+
721+
diesel::delete(
722+
dsl::db_metadata_nexus
723+
.filter(dsl::nexus_id.eq(nexus_id.into_untyped_uuid())),
724+
)
725+
.execute_async(&*conn)
726+
.await
727+
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))?;
728+
729+
Ok(())
730+
}
731+
732+
/// Propagate the nexus records to the database if and only if
733+
/// the blueprint is the current target.
734+
///
735+
/// If any of these records already exist, they are unmodified.
736+
pub async fn database_nexus_access_create(
737+
&self,
738+
opctx: &OpContext,
739+
blueprint: &nexus_types::deployment::Blueprint,
740+
) -> Result<(), Error> {
741+
opctx.authorize(authz::Action::Modify, &authz::FLEET).await?;
742+
743+
// TODO: Without https://github.com/oxidecomputer/omicron/pull/8863, we
744+
// treat all Nexuses as active. Some will become "not_yet", depending on
745+
// the Nexus Generation, once it exists.
746+
let active_nexus_zones = blueprint
747+
.all_omicron_zones(BlueprintZoneDisposition::is_in_service)
748+
.filter_map(|(_sled, zone_cfg)| {
749+
if zone_cfg.zone_type.is_nexus() {
750+
Some(zone_cfg)
751+
} else {
752+
None
753+
}
754+
});
755+
let new_nexuses = active_nexus_zones
756+
.map(|z| DbMetadataNexus::new(z.id, DbMetadataNexusState::Active))
757+
.collect::<Vec<_>>();
758+
759+
let conn = &*self.pool_connection_authorized(&opctx).await?;
760+
self.transaction_if_current_blueprint_is(
761+
&conn,
762+
"database_nexus_access_create",
763+
opctx,
764+
blueprint.id,
765+
|conn| {
766+
let new_nexuses = new_nexuses.clone();
767+
async move {
768+
use nexus_db_schema::schema::db_metadata_nexus::dsl;
769+
770+
diesel::insert_into(dsl::db_metadata_nexus)
771+
.values(new_nexuses)
772+
.on_conflict(dsl::nexus_id)
773+
.do_nothing()
774+
.execute_async(&*conn)
775+
.await?;
776+
Ok(())
777+
}
778+
.boxed()
779+
},
780+
)
781+
.await
782+
}
783+
704784
// Registers a Nexus instance as having active access to the database
705785
#[cfg(test)]
706786
async fn database_nexus_access_insert(
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
//! Manages deployment of records into the database.
6+
7+
use anyhow::anyhow;
8+
use nexus_db_queries::context::OpContext;
9+
use nexus_db_queries::db::DataStore;
10+
use nexus_types::deployment::Blueprint;
11+
12+
/// Idempotently ensure that the Nexus records for the zones are populated
13+
/// in the database.
14+
pub(crate) async fn deploy_db_metadata_nexus_records(
15+
opctx: &OpContext,
16+
datastore: &DataStore,
17+
blueprint: &Blueprint,
18+
) -> Result<(), anyhow::Error> {
19+
datastore
20+
.database_nexus_access_create(opctx, blueprint)
21+
.await
22+
.map_err(|err| anyhow!(err))?;
23+
Ok(())
24+
}

nexus/reconfigurator/execution/src/lib.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ use tokio::sync::watch;
3232
use update_engine::StepSuccess;
3333
use update_engine::StepWarning;
3434
use update_engine::merge_anyhow_list;
35+
3536
mod clickhouse;
3637
mod cockroachdb;
38+
mod database;
3739
mod dns;
3840
mod omicron_physical_disks;
3941
mod omicron_sled_config;
@@ -196,6 +198,13 @@ pub async fn realize_blueprint(
196198
)
197199
.into_shared();
198200

201+
register_deploy_db_metadata_nexus_records_step(
202+
&engine.for_component(ExecutionComponent::SledList),
203+
&opctx,
204+
datastore,
205+
blueprint,
206+
);
207+
199208
register_deploy_sled_configs_step(
200209
&engine.for_component(ExecutionComponent::SledAgent),
201210
&opctx,
@@ -390,6 +399,28 @@ fn register_sled_list_step<'a>(
390399
.register()
391400
}
392401

402+
fn register_deploy_db_metadata_nexus_records_step<'a>(
403+
registrar: &ComponentRegistrar<'_, 'a>,
404+
opctx: &'a OpContext,
405+
datastore: &'a DataStore,
406+
blueprint: &'a Blueprint,
407+
) {
408+
registrar
409+
.new_step(
410+
ExecutionStepId::Ensure,
411+
"Ensure db_metadata_nexus_state records exist",
412+
async move |_cx| {
413+
database::deploy_db_metadata_nexus_records(
414+
opctx, &datastore, &blueprint,
415+
)
416+
.await
417+
.context("ensuring db_metadata_nexus_state")?;
418+
StepSuccess::new(()).into()
419+
},
420+
)
421+
.register();
422+
}
423+
393424
fn register_deploy_sled_configs_step<'a>(
394425
registrar: &ComponentRegistrar<'_, 'a>,
395426
opctx: &'a OpContext,

nexus/reconfigurator/execution/src/omicron_zones.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,13 @@ async fn clean_up_expunged_zones_impl<R: CleanupResolver>(
7272
));
7373

7474
let result = match &config.zone_type {
75-
// Zones which need no cleanup work after expungement.
76-
BlueprintZoneType::Nexus(_) => None,
77-
7875
// Zones which need cleanup after expungement.
76+
BlueprintZoneType::Nexus(_) => Some(
77+
datastore
78+
.database_nexus_access_delete(&opctx, config.id)
79+
.await
80+
.map_err(|err| anyhow::anyhow!(err)),
81+
),
7982
BlueprintZoneType::CockroachDb(_) => {
8083
if decommission_cockroach {
8184
Some(

0 commit comments

Comments
 (0)