Skip to content

Commit

Permalink
Nexus: insert RSS blueprint and make it the target during handoff
Browse files Browse the repository at this point in the history
  • Loading branch information
jgallagher committed Mar 11, 2024
1 parent 56a4d55 commit 5b8156b
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 7 deletions.
30 changes: 25 additions & 5 deletions nexus/db-queries/src/db/datastore/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@ impl DataStore {
&self,
opctx: &OpContext,
blueprint: &Blueprint,
) -> Result<(), Error> {
let conn = self.pool_connection_authorized(opctx).await?;
Self::blueprint_insert_on_connection(&conn, opctx, blueprint).await
}

/// Variant of [Self::blueprint_insert] which may be called from a
/// transaction context.
pub(crate) async fn blueprint_insert_on_connection(
conn: &async_bb8_diesel::Connection<DbConnection>,
opctx: &OpContext,
blueprint: &Blueprint,
) -> Result<(), Error> {
opctx
.authorize(authz::Action::Modify, &authz::BLUEPRINT_CONFIG)
Expand Down Expand Up @@ -152,8 +163,7 @@ impl DataStore {
// batch rather than making a bunch of round-trips to the database.
// We'd do that if we had an interface for doing that with bound
// parameters, etc. See oxidecomputer/omicron#973.
let pool = self.pool_connection_authorized(opctx).await?;
pool.transaction_async(|conn| async move {
conn.transaction_async(|conn| async move {
// Insert the row for the blueprint.
{
use db::schema::blueprint::dsl;
Expand Down Expand Up @@ -620,6 +630,18 @@ impl DataStore {
&self,
opctx: &OpContext,
target: BlueprintTarget,
) -> Result<(), Error> {
let conn = self.pool_connection_authorized(opctx).await?;
Self::blueprint_target_set_current_on_connection(&conn, opctx, target)
.await
}

/// Variant of [Self::blueprint_target_set_current] which may be called from
/// a transaction context.
pub(crate) async fn blueprint_target_set_current_on_connection(
conn: &async_bb8_diesel::Connection<DbConnection>,
opctx: &OpContext,
target: BlueprintTarget,
) -> Result<(), Error> {
opctx
.authorize(authz::Action::Modify, &authz::BLUEPRINT_CONFIG)
Expand All @@ -631,10 +653,8 @@ impl DataStore {
time_made_target: target.time_made_target,
};

let conn = self.pool_connection_authorized(opctx).await?;

query
.execute_async(&*conn)
.execute_async(conn)
.await
.map_err(|e| Error::from(query.decode_error(e)))?;

Expand Down
66 changes: 64 additions & 2 deletions nexus/db-queries/src/db/datastore/rack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ use nexus_db_model::PasswordHashString;
use nexus_db_model::SiloUser;
use nexus_db_model::SiloUserPasswordHash;
use nexus_db_model::SledUnderlaySubnetAllocation;
use nexus_types::deployment::Blueprint;
use nexus_types::deployment::BlueprintTarget;
use nexus_types::external_api::params as external_params;
use nexus_types::external_api::shared;
use nexus_types::external_api::shared::IdentityType;
Expand All @@ -68,6 +70,7 @@ use uuid::Uuid;
pub struct RackInit {
pub rack_id: Uuid,
pub rack_subnet: IpNetwork,
pub blueprint: Blueprint,
pub services: Vec<internal_params::ServicePutRequest>,
pub datasets: Vec<Dataset>,
pub service_ip_pool_ranges: Vec<IpRange>,
Expand All @@ -85,6 +88,8 @@ pub struct RackInit {
enum RackInitError {
AddingIp(Error),
AddingNic(Error),
BlueprintInsert(Error),
BlueprintTargetSet(Error),
ServiceInsert(Error),
DatasetInsert { err: AsyncInsertError, zpool_id: Uuid },
RackUpdate { err: DieselError, rack_id: Uuid },
Expand Down Expand Up @@ -126,6 +131,12 @@ impl From<RackInitError> for Error {
RackInitError::ServiceInsert(err) => Error::internal_error(
&format!("failed to insert Service record: {:#}", err),
),
RackInitError::BlueprintInsert(err) => Error::internal_error(
&format!("failed to insert Blueprint: {:#}", err),
),
RackInitError::BlueprintTargetSet(err) => Error::internal_error(
&format!("failed to insert set target Blueprint: {:#}", err),
),
RackInitError::RackUpdate { err, rack_id } => {
public_error_from_diesel(
err,
Expand Down Expand Up @@ -583,6 +594,7 @@ impl DataStore {
let service_pool = service_pool.clone();
async move {
let rack_id = rack_init.rack_id;
let blueprint = rack_init.blueprint;
let services = rack_init.services;
let datasets = rack_init.datasets;
let service_ip_pool_ranges = rack_init.service_ip_pool_ranges;
Expand All @@ -608,7 +620,7 @@ impl DataStore {
return Ok::<_, DieselError>(rack);
}

// Otherwise, insert services and datasets.
// Otherwise, insert blueprint and datasets.

// Set up the IP pool for internal services.
for range in service_ip_pool_ranges {
Expand All @@ -629,6 +641,46 @@ impl DataStore {
})?;
}

// Insert the RSS-generated blueprint.
Self::blueprint_insert_on_connection(
&conn,
opctx,
&blueprint,
).await
.map_err(|e| {
warn!(
log,
"Initializing Rack: Failed to insert blueprint"
);
err.set(RackInitError::BlueprintInsert(e)).unwrap();
DieselError::RollbackTransaction
})?;

// Mark the RSS-generated blueprint as the current target,
// DISABLED. We may change this to enabled in the future
// when more of Reconfigurator is automated, but for now we
// require a support operation to enable it.
Self::blueprint_target_set_current_on_connection(
&conn,
opctx,
BlueprintTarget {
target_id: blueprint.id,
enabled: false,
time_made_target: Utc::now(),
},
)
.await
.map_err(|e| {
warn!(
log,
"Initializing Rack: \
Failed to set blueprint as target"
);
err.set(RackInitError::BlueprintTargetSet(e))
.unwrap();
DieselError::RollbackTransaction
})?;

// Allocate records for all services.
for service in services {
self.rack_populate_service_records(
Expand Down Expand Up @@ -882,7 +934,7 @@ mod test {
};
use omicron_common::api::internal::shared::SourceNatConfig;
use omicron_test_utils::dev;
use std::collections::HashMap;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV6};
use std::num::NonZeroU32;

Expand All @@ -893,6 +945,16 @@ mod test {
RackInit {
rack_id: Uuid::parse_str(nexus_test_utils::RACK_UUID).unwrap(),
rack_subnet: nexus_test_utils::RACK_SUBNET.parse().unwrap(),
blueprint: Blueprint {
id: Uuid::new_v4(),
omicron_zones: BTreeMap::new(),
zones_in_service: BTreeSet::new(),
parent_blueprint_id: None,
internal_dns_version: Generation::new().next(),
time_created: Utc::now(),
creator: "test suite".to_string(),
comment: "test suite".to_string(),
},
services: vec![],
datasets: vec![],
service_ip_pool_ranges: vec![],
Expand Down
1 change: 1 addition & 0 deletions nexus/src/app/rack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ impl super::Nexus {
RackInit {
rack_subnet: rack_network_config.rack_subnet.into(),
rack_id,
blueprint: request.blueprint,
services: request.services,
datasets,
service_ip_pool_ranges,
Expand Down

0 comments on commit 5b8156b

Please sign in to comment.