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
Original file line number Diff line number Diff line change
Expand Up @@ -574,24 +574,24 @@ parent: 3f00b694-1b16-4aaa-8f78-e6b3a527b434


omicron zones at generation 3:
---------------------------------------------------------------------------------------------
zone type zone id disposition underlay IP
---------------------------------------------------------------------------------------------
crucible 0903299a-6296-44f0-8ab9-7c70b5766a05 in service fd00:1122:3344:101::25
crucible 2b6b3cfd-4524-465b-ac6e-10be9ab6d4d4 in service fd00:1122:3344:101::27
crucible 3e0ff677-2ca8-4124-9fef-7c23ac2da6fa in service fd00:1122:3344:101::2d
crucible 512758d0-335f-4c94-9afe-c82f6f127421 in service fd00:1122:3344:101::2a
crucible 8ae67b12-ca74-40d3-a55e-90456cd623ea in service fd00:1122:3344:101::26
crucible 918c8cbc-1c62-4de5-9cf2-c4153a3d1a7e in service fd00:1122:3344:101::2e
crucible be422e7a-16d0-426e-8567-da0aed7200d4 in service fd00:1122:3344:101::28
crucible ea50f438-1b5e-4d61-bd65-46d360f590ee in service fd00:1122:3344:101::2b
crucible f055a042-9d1b-4931-8268-d94cac801d7e in service fd00:1122:3344:101::29
crucible f33e09d1-e3d7-4341-baf2-5f079f3679e5 in service fd00:1122:3344:101::2c
crucible_pantry 100e20aa-1816-4195-8d76-08beace10332 in service fd00:1122:3344:101::24
external_dns 9995de32-dd52-4eb1-b0eb-141eb84bc739 expunged fd00:1122:3344:101::23
internal_dns 171cabf0-8635-42e7-8ea1-2a1d2a2daf55 in service fd00:1122:3344:3::1
internal_ntp 7b4bccad-9869-48da-8320-2dc82752deea in service fd00:1122:3344:101::21
nexus 5b01b0e0-5cdf-4b34-b0a6-c947cbbdb8be in service fd00:1122:3344:101::22
----------------------------------------------------------------------------------------------
zone type zone id disposition underlay IP
----------------------------------------------------------------------------------------------
crucible 0903299a-6296-44f0-8ab9-7c70b5766a05 in service fd00:1122:3344:101::25
crucible 2b6b3cfd-4524-465b-ac6e-10be9ab6d4d4 in service fd00:1122:3344:101::27
crucible 3e0ff677-2ca8-4124-9fef-7c23ac2da6fa in service fd00:1122:3344:101::2d
crucible 512758d0-335f-4c94-9afe-c82f6f127421 in service fd00:1122:3344:101::2a
crucible 8ae67b12-ca74-40d3-a55e-90456cd623ea in service fd00:1122:3344:101::26
crucible 918c8cbc-1c62-4de5-9cf2-c4153a3d1a7e in service fd00:1122:3344:101::2e
crucible be422e7a-16d0-426e-8567-da0aed7200d4 in service fd00:1122:3344:101::28
crucible ea50f438-1b5e-4d61-bd65-46d360f590ee in service fd00:1122:3344:101::2b
crucible f055a042-9d1b-4931-8268-d94cac801d7e in service fd00:1122:3344:101::29
crucible f33e09d1-e3d7-4341-baf2-5f079f3679e5 in service fd00:1122:3344:101::2c
crucible_pantry 100e20aa-1816-4195-8d76-08beace10332 in service fd00:1122:3344:101::24
external_dns 9995de32-dd52-4eb1-b0eb-141eb84bc739 expunged fd00:1122:3344:101::23
internal_dns 171cabf0-8635-42e7-8ea1-2a1d2a2daf55 in service fd00:1122:3344:3::1
internal_ntp 7b4bccad-9869-48da-8320-2dc82752deea in service fd00:1122:3344:101::21
nexus 5b01b0e0-5cdf-4b34-b0a6-c947cbbdb8be in service fd00:1122:3344:101::22


COCKROACHDB SETTINGS:
Expand Down Expand Up @@ -890,25 +890,25 @@ parent: 366b0b68-d80e-4bc1-abd3-dc69837847e0


omicron zones at generation 4:
---------------------------------------------------------------------------------------------
zone type zone id disposition underlay IP
---------------------------------------------------------------------------------------------
crucible 0903299a-6296-44f0-8ab9-7c70b5766a05 in service fd00:1122:3344:101::25
crucible 2b6b3cfd-4524-465b-ac6e-10be9ab6d4d4 in service fd00:1122:3344:101::27
crucible 3e0ff677-2ca8-4124-9fef-7c23ac2da6fa in service fd00:1122:3344:101::2d
crucible 512758d0-335f-4c94-9afe-c82f6f127421 in service fd00:1122:3344:101::2a
crucible 8ae67b12-ca74-40d3-a55e-90456cd623ea in service fd00:1122:3344:101::26
crucible 918c8cbc-1c62-4de5-9cf2-c4153a3d1a7e in service fd00:1122:3344:101::2e
crucible be422e7a-16d0-426e-8567-da0aed7200d4 in service fd00:1122:3344:101::28
crucible ea50f438-1b5e-4d61-bd65-46d360f590ee in service fd00:1122:3344:101::2b
crucible f055a042-9d1b-4931-8268-d94cac801d7e in service fd00:1122:3344:101::29
crucible f33e09d1-e3d7-4341-baf2-5f079f3679e5 in service fd00:1122:3344:101::2c
crucible_pantry 100e20aa-1816-4195-8d76-08beace10332 in service fd00:1122:3344:101::24
external_dns 9995de32-dd52-4eb1-b0eb-141eb84bc739 expunged fd00:1122:3344:101::23
external_dns d786ef4a-5acb-4f5d-a732-a00addf986b5 in service fd00:1122:3344:101::2f
internal_dns 171cabf0-8635-42e7-8ea1-2a1d2a2daf55 in service fd00:1122:3344:3::1
internal_ntp 7b4bccad-9869-48da-8320-2dc82752deea in service fd00:1122:3344:101::21
nexus 5b01b0e0-5cdf-4b34-b0a6-c947cbbdb8be in service fd00:1122:3344:101::22
----------------------------------------------------------------------------------------------
zone type zone id disposition underlay IP
----------------------------------------------------------------------------------------------
crucible 0903299a-6296-44f0-8ab9-7c70b5766a05 in service fd00:1122:3344:101::25
crucible 2b6b3cfd-4524-465b-ac6e-10be9ab6d4d4 in service fd00:1122:3344:101::27
crucible 3e0ff677-2ca8-4124-9fef-7c23ac2da6fa in service fd00:1122:3344:101::2d
crucible 512758d0-335f-4c94-9afe-c82f6f127421 in service fd00:1122:3344:101::2a
crucible 8ae67b12-ca74-40d3-a55e-90456cd623ea in service fd00:1122:3344:101::26
crucible 918c8cbc-1c62-4de5-9cf2-c4153a3d1a7e in service fd00:1122:3344:101::2e
crucible be422e7a-16d0-426e-8567-da0aed7200d4 in service fd00:1122:3344:101::28
crucible ea50f438-1b5e-4d61-bd65-46d360f590ee in service fd00:1122:3344:101::2b
crucible f055a042-9d1b-4931-8268-d94cac801d7e in service fd00:1122:3344:101::29
crucible f33e09d1-e3d7-4341-baf2-5f079f3679e5 in service fd00:1122:3344:101::2c
crucible_pantry 100e20aa-1816-4195-8d76-08beace10332 in service fd00:1122:3344:101::24
external_dns 9995de32-dd52-4eb1-b0eb-141eb84bc739 expunged fd00:1122:3344:101::23
external_dns d786ef4a-5acb-4f5d-a732-a00addf986b5 in service fd00:1122:3344:101::2f
internal_dns 171cabf0-8635-42e7-8ea1-2a1d2a2daf55 in service fd00:1122:3344:3::1
internal_ntp 7b4bccad-9869-48da-8320-2dc82752deea in service fd00:1122:3344:101::21
nexus 5b01b0e0-5cdf-4b34-b0a6-c947cbbdb8be in service fd00:1122:3344:101::22


COCKROACHDB SETTINGS:
Expand Down
150 changes: 70 additions & 80 deletions nexus/db-model/src/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,8 @@ pub struct BpOmicronZone {
pub snat_last_port: Option<SqlU16>,

disposition: DbBpZoneDisposition,
disposition_expunged_as_of_generation: Option<Generation>,
disposition_expunged_ready_for_cleanup: bool,

pub external_ip_id: Option<DbTypedUuid<ExternalIpKind>>,
pub filesystem_pool: Option<DbTypedUuid<ZpoolKind>>,
Expand All @@ -483,6 +485,12 @@ impl BpOmicronZone {
.external_networking()
.map(|(ip, _)| ip.id().into());

let DbBpZoneDispositionColumns {
disposition,
expunged_as_of_generation: disposition_expunged_as_of_generation,
expunged_ready_for_cleanup: disposition_expunged_ready_for_cleanup,
} = blueprint_zone.disposition.into();

// Create a dummy record to start, then fill in the rest
let mut bp_omicron_zone = BpOmicronZone {
// Fill in the known fields that don't require inspecting
Expand All @@ -495,7 +503,9 @@ impl BpOmicronZone {
.filesystem_pool
.as_ref()
.map(|pool| pool.id().into()),
disposition: to_db_bp_zone_disposition(blueprint_zone.disposition),
disposition,
disposition_expunged_as_of_generation,
disposition_expunged_ready_for_cleanup,
zone_type: blueprint_zone.zone_type.kind().into(),

// Set the remainder of the fields to a default
Expand Down Expand Up @@ -879,8 +889,16 @@ impl BpOmicronZone {
}
};

let disposition_cols = DbBpZoneDispositionColumns {
disposition: self.disposition,
expunged_as_of_generation: self
.disposition_expunged_as_of_generation,
expunged_ready_for_cleanup: self
.disposition_expunged_ready_for_cleanup,
};

Ok(BlueprintZoneConfig {
disposition: self.disposition.into(),
disposition: disposition_cols.try_into()?,
id: self.id.into(),
filesystem_pool: self
.filesystem_pool
Expand All @@ -907,30 +925,63 @@ impl_enum_type!(

// Enum values
InService => b"in_service"
Quiesced => b"quiesced"
Expunged => b"expunged"
);

/// Converts a [`BlueprintZoneDisposition`] to a version that can be inserted
/// into a database.
pub fn to_db_bp_zone_disposition(
disposition: BlueprintZoneDisposition,
) -> DbBpZoneDisposition {
match disposition {
BlueprintZoneDisposition::InService => DbBpZoneDisposition::InService,
BlueprintZoneDisposition::Quiesced => DbBpZoneDisposition::Quiesced,
BlueprintZoneDisposition::Expunged => DbBpZoneDisposition::Expunged,
struct DbBpZoneDispositionColumns {
disposition: DbBpZoneDisposition,
expunged_as_of_generation: Option<Generation>,
expunged_ready_for_cleanup: bool,
}

impl From<BlueprintZoneDisposition> for DbBpZoneDispositionColumns {
fn from(value: BlueprintZoneDisposition) -> Self {
let (
disposition,
disposition_expunged_as_of_generation,
disposition_expunged_ready_for_cleanup,
) = match value {
BlueprintZoneDisposition::InService => {
(DbBpZoneDisposition::InService, None, false)
}
BlueprintZoneDisposition::Expunged {
as_of_generation,
ready_for_cleanup,
} => (
DbBpZoneDisposition::Expunged,
Some(Generation(as_of_generation)),
ready_for_cleanup,
),
};
Self {
disposition,
expunged_as_of_generation: disposition_expunged_as_of_generation,
expunged_ready_for_cleanup: disposition_expunged_ready_for_cleanup,
}
}
}

impl From<DbBpZoneDisposition> for BlueprintZoneDisposition {
fn from(disposition: DbBpZoneDisposition) -> Self {
match disposition {
DbBpZoneDisposition::InService => {
BlueprintZoneDisposition::InService
impl TryFrom<DbBpZoneDispositionColumns> for BlueprintZoneDisposition {
type Error = anyhow::Error;

fn try_from(
value: DbBpZoneDispositionColumns,
) -> Result<Self, Self::Error> {
match (value.disposition, value.expunged_as_of_generation) {
(DbBpZoneDisposition::InService, None) => Ok(Self::InService),
(DbBpZoneDisposition::Expunged, Some(as_of_generation)) => {
Ok(Self::Expunged {
as_of_generation: *as_of_generation,
ready_for_cleanup: value.expunged_ready_for_cleanup,
})
}
DbBpZoneDisposition::Quiesced => BlueprintZoneDisposition::Quiesced,
DbBpZoneDisposition::Expunged => BlueprintZoneDisposition::Expunged,
(DbBpZoneDisposition::InService, Some(_))
| (DbBpZoneDisposition::Expunged, None) => Err(anyhow!(
"illegal database state (CHECK constraint broken?!): \
disposition {:?}, disposition_expunged_as_of_generation {:?}",
value.disposition,
value.expunged_as_of_generation,
)),
}
}
}
Expand Down Expand Up @@ -1086,64 +1137,3 @@ impl BpClickhouseServerZoneIdToNodeId {
})
}
}

mod diesel_util {
use crate::{
schema::bp_omicron_zone::disposition, to_db_bp_zone_disposition,
DbBpZoneDisposition,
};
use diesel::{
helper_types::EqAny, prelude::*, query_dsl::methods::FilterDsl,
};
use nexus_types::deployment::{
BlueprintZoneDisposition, BlueprintZoneFilter,
};

/// An extension trait to apply a [`BlueprintZoneFilter`] to a Diesel
/// expression.
///
/// This is applicable to any Diesel expression which includes the
/// `bp_omicron_zone` table.
///
/// This needs to live here, rather than in `nexus-db-queries`, because it
/// names the `DbBpZoneDisposition` type which is private to this crate.
pub trait ApplyBlueprintZoneFilterExt {
type Output;

/// Applies a [`BlueprintZoneFilter`] to a Diesel expression.
fn blueprint_zone_filter(
self,
filter: BlueprintZoneFilter,
) -> Self::Output;
}

impl<E> ApplyBlueprintZoneFilterExt for E
where
E: FilterDsl<BlueprintZoneFilterQuery>,
{
type Output = E::Output;

fn blueprint_zone_filter(
self,
filter: BlueprintZoneFilter,
) -> Self::Output {
// This is only boxed for ease of reference above.
let all_matching_dispositions: BoxedIterator<DbBpZoneDisposition> =
Box::new(
BlueprintZoneDisposition::all_matching(filter)
.map(to_db_bp_zone_disposition),
);

FilterDsl::filter(
self,
disposition.eq_any(all_matching_dispositions),
)
}
}

type BoxedIterator<T> = Box<dyn Iterator<Item = T>>;
type BlueprintZoneFilterQuery =
EqAny<disposition, BoxedIterator<DbBpZoneDisposition>>;
}

pub use diesel_util::ApplyBlueprintZoneFilterExt;
2 changes: 2 additions & 0 deletions nexus/db-model/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1753,6 +1753,8 @@ table! {
snat_first_port -> Nullable<Int4>,
snat_last_port -> Nullable<Int4>,
disposition -> crate::DbBpZoneDispositionEnum,
disposition_expunged_as_of_generation -> Nullable<Int8>,
disposition_expunged_ready_for_cleanup -> Bool,
external_ip_id -> Nullable<Uuid>,
filesystem_pool -> Nullable<Uuid>,
}
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 @@ -17,7 +17,7 @@ use std::collections::BTreeMap;
///
/// 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: SemverVersion = SemverVersion::new(124, 0, 0);
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(125, 0, 0);

/// List of all past database schema versions, in *reverse* order
///
Expand All @@ -29,6 +29,7 @@ static KNOWN_VERSIONS: Lazy<Vec<KnownVersion>> = Lazy::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(125, "blueprint-disposition-expunged-cleanup"),
KnownVersion::new(124, "support-read-only-region-replacement"),
KnownVersion::new(123, "vpc-subnet-contention"),
KnownVersion::new(122, "tuf-artifact-replication"),
Expand Down
5 changes: 4 additions & 1 deletion nexus/db-queries/src/db/datastore/support_bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,10 @@ mod test {
for zones in bp.blueprint_zones.values_mut() {
for mut zone in &mut zones.zones {
if zone.id == bundle.assigned_nexus.unwrap().into() {
zone.disposition = BlueprintZoneDisposition::Expunged;
zone.disposition = BlueprintZoneDisposition::Expunged {
as_of_generation: *Generation::new(),
ready_for_cleanup: false,
};
}
}
}
Expand Down
31 changes: 13 additions & 18 deletions nexus/db-queries/src/db/datastore/vpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use crate::db::collection_insert::DatastoreCollection;
use crate::db::error::public_error_from_diesel;
use crate::db::error::ErrorHandler;
use crate::db::identity::Resource;
use crate::db::model::ApplyBlueprintZoneFilterExt;
use crate::db::model::ApplySledFilterExt;
use crate::db::model::IncompleteVpc;
use crate::db::model::InstanceNetworkInterface;
Expand Down Expand Up @@ -55,13 +54,13 @@ use nexus_db_fixed_data::vpc::SERVICES_INTERNET_GATEWAY_DEFAULT_ROUTE_V4;
use nexus_db_fixed_data::vpc::SERVICES_INTERNET_GATEWAY_DEFAULT_ROUTE_V6;
use nexus_db_fixed_data::vpc::SERVICES_INTERNET_GATEWAY_ID;
use nexus_db_fixed_data::vpc::SERVICES_VPC_ID;
use nexus_db_model::DbBpZoneDisposition;
use nexus_db_model::ExternalIp;
use nexus_db_model::InternetGateway;
use nexus_db_model::InternetGatewayIpAddress;
use nexus_db_model::InternetGatewayIpPool;
use nexus_db_model::IpPoolRange;
use nexus_db_model::NetworkInterfaceKind;
use nexus_types::deployment::BlueprintZoneFilter;
use nexus_types::deployment::SledFilter;
use omicron_common::api::external::http_pagination::PaginatedBy;
use omicron_common::api::external::CreateResult;
Expand Down Expand Up @@ -798,8 +797,11 @@ impl DataStore {
)
// Filter out services that are expunged and shouldn't be resolved
// here.
.blueprint_zone_filter(
BlueprintZoneFilter::ShouldDeployVpcFirewallRules,
//
// TODO: We should reference a rendezvous table instead of filtering
// for in-service zones.
.filter(
bp_omicron_zone::disposition.eq(DbBpZoneDisposition::InService),
)
.filter(service_network_interface::vpc_id.eq(vpc_id))
.filter(service_network_interface::time_deleted.is_null())
Expand Down Expand Up @@ -3332,31 +3334,24 @@ mod tests {
.expect("failed to undo ineligible sleds");
assert_service_sled_ids(&datastore, &sled_ids).await;

// Make a new blueprint marking one of the zones as quiesced and one as
// expunged. Ensure that the sled with *quiesced* zone is returned by
// vpc_resolve_to_sleds, but the sled with the *expunged* zone is not.
// (But other services are still running.)
// Make a new blueprint marking one of the zones as expunged. Ensure
// that the sled the expunged zone is not returned by
// vpc_resolve_to_sleds. (But other services are still running.)
let bp4 = {
let mut bp4 = bp3.clone();
bp4.id = BlueprintUuid::new_v4();
bp4.parent_blueprint_id = Some(bp3.id);

// Sled index 2's Nexus is quiesced (should be included).
let sled2 = bp4
.blueprint_zones
.get_mut(&sled_ids[2])
.expect("zones for sled");
sled2.zones.iter_mut().next().unwrap().disposition =
BlueprintZoneDisposition::Quiesced;
sled2.generation = sled2.generation.next();

// Sled index 3's zone is expunged (should be excluded).
let sled3 = bp4
.blueprint_zones
.get_mut(&sled_ids[3])
.expect("zones for sled");
sled3.zones.iter_mut().next().unwrap().disposition =
BlueprintZoneDisposition::Expunged;
BlueprintZoneDisposition::Expunged {
as_of_generation: Generation::new(),
ready_for_cleanup: false,
};
sled3.generation = sled3.generation.next();

bp4
Expand Down
Loading