Skip to content
Open
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
78 changes: 54 additions & 24 deletions nexus/db-queries/src/db/datastore/sled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2410,6 +2410,9 @@ pub(in crate::db::datastore) mod test {
use crate::db::pub_test_utils::simulated_sleds::test_sled_resources;
use crate::db::pub_test_utils::simulated_sleds::upsert_sleds_from_system;
use crate::db::queries::ALLOW_FULL_TABLE_SCAN_SQL;
use crate::db::queries::sled_reservation::BANNED_SLEDS_SENTINEL;
use crate::db::queries::sled_reservation::REQUIRED_SLEDS_SENTINEL;
use crate::db::queries::sled_reservation::SLED_HAS_SPACE_SENTINEL;
use anyhow::{Context, Result};
use async_bb8_diesel::AsyncConnection;
use async_bb8_diesel::AsyncSimpleConnection;
Expand Down Expand Up @@ -2859,6 +2862,22 @@ pub(in crate::db::datastore) mod test {
anti_affinity_policy: Option<AffinityPolicy>,
}

/// The result of [`Instance::insert_resource`].
#[derive(Debug, PartialEq, Eq)]
enum InsertResourceOutcome {
/// The resource was successfully inserted.
Inserted,

/// The insert query was rejected.
Rejected {
/// The sentinel value raised by the database.
///
/// Compare against the sentinels defined in
/// [`crate::db::queries::sled_reservation`].
sentinel: &'static str,
},
}

impl Instance {
fn new() -> Self {
Self::new_with_id(InstanceUuid::new_v4())
Expand Down Expand Up @@ -2928,15 +2947,13 @@ pub(in crate::db::datastore) mod test {

// This is the second half of creating a sled reservation.
// It can be called during tests trying to invoke contention manually.
//
// Returns "true" if the INSERT succeeded
async fn insert_resource(
&self,
datastore: &DataStore,
propolis_id: PropolisUuid,
sled_id: SledUuid,
reservation_reason: SledReservationReason,
) -> bool {
) -> InsertResourceOutcome {
assert!(self.force_onto_sled.is_none());

let resource = SledResourceVmm::new(
Expand All @@ -2956,15 +2973,18 @@ pub(in crate::db::datastore) mod test {
.execute_async(&*conn)
.await
{
Ok(rows_inserted) => rows_inserted > 0,

// Without local storage allocations, we should never get Ok(0)
// back.
Ok(0) => panic!(
"insert query inserted no rows without raising a sentinel"
),
Ok(_) => InsertResourceOutcome::Inserted,
Err(e) => {
if matches_sentinel(&e, &SLED_INSERT_QUERY_SENTINELS)
.is_some()
{
false
} else {
panic!("{e}")
match matches_sentinel(&e, &SLED_INSERT_QUERY_SENTINELS) {
Some(sentinel) => {
InsertResourceOutcome::Rejected { sentinel }
}
None => panic!("{e}"),
}
}
}
Expand Down Expand Up @@ -3861,29 +3881,33 @@ pub(in crate::db::datastore) mod test {
// Inserting onto sleds[1..3] should fail -- the affinity requirement
// should bind us to sleds[0].
for i in 1..=3 {
assert!(
!test_instance
assert_eq!(
test_instance
.insert_resource(
&datastore,
PropolisUuid::new_v4(),
sleds[i].id(),
SledReservationReason::Start,
)
.await,
InsertResourceOutcome::Rejected {
sentinel: REQUIRED_SLEDS_SENTINEL
},
"Shouldn't have been able to insert into sled {i}"
)
}

// Inserting into sleds[0] should succeed
assert!(
assert_eq!(
test_instance
.insert_resource(
&datastore,
PropolisUuid::new_v4(),
sleds[0].id(),
SledReservationReason::Start,
)
.await
.await,
InsertResourceOutcome::Inserted,
);

db.terminate().await;
Expand Down Expand Up @@ -3963,28 +3987,30 @@ pub(in crate::db::datastore) mod test {

// Inserting onto sleds[0] should fail -- the anti-affinity requirement
// should prevent us from inserting there.
assert!(
!test_instance
assert_eq!(
test_instance
.insert_resource(
&datastore,
PropolisUuid::new_v4(),
sleds[0].id(),
SledReservationReason::Start,
)
.await,
InsertResourceOutcome::Rejected { sentinel: BANNED_SLEDS_SENTINEL },
"Shouldn't have been able to insert into sleds[0]"
);

// Inserting into sleds[1] should succeed
assert!(
assert_eq!(
test_instance
.insert_resource(
&datastore,
PropolisUuid::new_v4(),
sleds[1].id(),
SledReservationReason::Start,
)
.await
.await,
InsertResourceOutcome::Inserted,
);

db.terminate().await;
Expand Down Expand Up @@ -4049,29 +4075,33 @@ pub(in crate::db::datastore) mod test {
// Inserting onto sleds[0, 2, 3] should fail - there shouldn't
// be enough space on these sleds.
for i in [0, 2, 3] {
assert!(
!test_instance
assert_eq!(
test_instance
.insert_resource(
&datastore,
PropolisUuid::new_v4(),
sleds[i].id(),
SledReservationReason::Start,
)
.await,
"Shouldn't have been able to insert into sleds[i]"
InsertResourceOutcome::Rejected {
sentinel: SLED_HAS_SPACE_SENTINEL
},
"Shouldn't have been able to insert into sleds[{i}]"
);
}

// Inserting into sleds[1] should succeed
assert!(
assert_eq!(
test_instance
.insert_resource(
&datastore,
PropolisUuid::new_v4(),
sleds[1].id(),
SledReservationReason::Start,
)
.await
.await,
InsertResourceOutcome::Inserted,
);

db.terminate().await;
Expand Down
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.