Skip to content

Commit be2bc89

Browse files
jmpesphawkw
andauthored
Fix broken disk list (#9553)
For shame! --------- Co-authored-by: Eliza Weisman <eliza@elizas.website>
1 parent e00aaba commit be2bc89

File tree

2 files changed

+136
-60
lines changed

2 files changed

+136
-60
lines changed

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

Lines changed: 61 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -445,46 +445,16 @@ impl DataStore {
445445
.await
446446
}
447447

448-
/// List disks associated with a given instance by name.
449-
pub async fn instance_list_disks_on_conn(
450-
&self,
448+
/// Consume a query result listing all parts of the higher level Disk type,
449+
/// and assemble it.
450+
async fn process_tuples_to_disk_list(
451451
conn: &async_bb8_diesel::Connection<DbConnection>,
452-
instance_id: Uuid,
453-
pagparams: &PaginatedBy<'_>,
452+
results: Vec<(
453+
model::Disk,
454+
Option<DiskTypeCrucible>,
455+
Option<DiskTypeLocalStorage>,
456+
)>,
454457
) -> ListResultVec<Disk> {
455-
use nexus_db_schema::schema::disk::dsl;
456-
use nexus_db_schema::schema::disk_type_crucible::dsl as disk_type_crucible_dsl;
457-
use nexus_db_schema::schema::disk_type_local_storage::dsl as disk_type_local_storage_dsl;
458-
459-
let results = match pagparams {
460-
PaginatedBy::Id(pagparams) => {
461-
paginated(dsl::disk, dsl::id, &pagparams)
462-
}
463-
PaginatedBy::Name(pagparams) => paginated(
464-
dsl::disk,
465-
dsl::name,
466-
&pagparams.map_name(|n| Name::ref_cast(n)),
467-
),
468-
}
469-
.left_join(
470-
disk_type_crucible_dsl::disk_type_crucible
471-
.on(dsl::id.eq(disk_type_crucible_dsl::disk_id)),
472-
)
473-
.left_join(
474-
disk_type_local_storage_dsl::disk_type_local_storage
475-
.on(dsl::id.eq(disk_type_local_storage_dsl::disk_id)),
476-
)
477-
.filter(dsl::time_deleted.is_null())
478-
.filter(dsl::attach_instance_id.eq(instance_id))
479-
.select((
480-
model::Disk::as_select(),
481-
Option::<DiskTypeCrucible>::as_select(),
482-
Option::<DiskTypeLocalStorage>::as_select(),
483-
))
484-
.get_results_async(conn)
485-
.await
486-
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))?;
487-
488458
let mut list = Vec::with_capacity(results.len());
489459

490460
for result in results {
@@ -555,6 +525,49 @@ impl DataStore {
555525
Ok(list)
556526
}
557527

528+
/// List disks associated with a given instance by name.
529+
pub async fn instance_list_disks_on_conn(
530+
&self,
531+
conn: &async_bb8_diesel::Connection<DbConnection>,
532+
instance_id: Uuid,
533+
pagparams: &PaginatedBy<'_>,
534+
) -> ListResultVec<Disk> {
535+
use nexus_db_schema::schema::disk::dsl;
536+
use nexus_db_schema::schema::disk_type_crucible::dsl as disk_type_crucible_dsl;
537+
use nexus_db_schema::schema::disk_type_local_storage::dsl as disk_type_local_storage_dsl;
538+
539+
let results = match pagparams {
540+
PaginatedBy::Id(pagparams) => {
541+
paginated(dsl::disk, dsl::id, &pagparams)
542+
}
543+
PaginatedBy::Name(pagparams) => paginated(
544+
dsl::disk,
545+
dsl::name,
546+
&pagparams.map_name(Name::ref_cast),
547+
),
548+
}
549+
.left_join(
550+
disk_type_crucible_dsl::disk_type_crucible
551+
.on(dsl::id.eq(disk_type_crucible_dsl::disk_id)),
552+
)
553+
.left_join(
554+
disk_type_local_storage_dsl::disk_type_local_storage
555+
.on(dsl::id.eq(disk_type_local_storage_dsl::disk_id)),
556+
)
557+
.filter(dsl::time_deleted.is_null())
558+
.filter(dsl::attach_instance_id.eq(instance_id))
559+
.select((
560+
model::Disk::as_select(),
561+
Option::<DiskTypeCrucible>::as_select(),
562+
Option::<DiskTypeLocalStorage>::as_select(),
563+
))
564+
.get_results_async(conn)
565+
.await
566+
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))?;
567+
568+
Self::process_tuples_to_disk_list(conn, results).await
569+
}
570+
558571
pub(super) async fn project_create_disk_in_txn(
559572
conn: &async_bb8_diesel::Connection<DbConnection>,
560573
err: OptionalError<Error>,
@@ -702,6 +715,9 @@ impl DataStore {
702715

703716
use nexus_db_schema::schema::disk::dsl;
704717
use nexus_db_schema::schema::disk_type_crucible::dsl as disk_type_crucible_dsl;
718+
use nexus_db_schema::schema::disk_type_local_storage::dsl as disk_type_local_storage_dsl;
719+
720+
let conn = self.pool_connection_authorized(opctx).await?;
705721

706722
let results = match pagparams {
707723
PaginatedBy::Id(pagparams) => {
@@ -717,37 +733,22 @@ impl DataStore {
717733
disk_type_crucible_dsl::disk_type_crucible
718734
.on(dsl::id.eq(disk_type_crucible_dsl::disk_id)),
719735
)
736+
.left_join(
737+
disk_type_local_storage_dsl::disk_type_local_storage
738+
.on(dsl::id.eq(disk_type_local_storage_dsl::disk_id)),
739+
)
720740
.filter(dsl::time_deleted.is_null())
721741
.filter(dsl::project_id.eq(authz_project.id()))
722742
.select((
723743
model::Disk::as_select(),
724744
Option::<DiskTypeCrucible>::as_select(),
745+
Option::<DiskTypeLocalStorage>::as_select(),
725746
))
726-
.get_results_async(&*self.pool_connection_authorized(opctx).await?)
747+
.get_results_async(&*conn)
727748
.await
728749
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))?;
729750

730-
let mut list = Vec::with_capacity(results.len());
731-
732-
for result in results {
733-
match result {
734-
(disk, Some(disk_type_crucible)) => {
735-
list.push(Disk::Crucible(CrucibleDisk {
736-
disk,
737-
disk_type_crucible,
738-
}));
739-
}
740-
741-
(disk, None) => {
742-
return Err(Error::internal_error(&format!(
743-
"disk {} is invalid!",
744-
disk.id(),
745-
)));
746-
}
747-
}
748-
}
749-
750-
Ok(list)
751+
Self::process_tuples_to_disk_list(&conn, results).await
751752
}
752753

753754
/// Attaches a disk to an instance, if both objects:

nexus/tests/integration_tests/disks.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2658,6 +2658,81 @@ async fn test_zpool_control_plane_storage_buffer(
26582658
.unwrap();
26592659
}
26602660

2661+
#[nexus_test]
2662+
async fn test_list_all_types_of_disk(cptestctx: &ControlPlaneTestContext) {
2663+
// Create three zpools, each with one dataset
2664+
DiskTestBuilder::new(&cptestctx)
2665+
.on_all_sleds()
2666+
.with_zpool_count(3)
2667+
.build()
2668+
.await;
2669+
2670+
// Assert default is still 16 GiB
2671+
assert_eq!(16, DiskTest::DEFAULT_ZPOOL_SIZE_GIB);
2672+
2673+
let client = &cptestctx.external_client;
2674+
create_project_and_pool(client).await;
2675+
2676+
let disks_url = get_disks_url();
2677+
2678+
// Distributed disk
2679+
let new_disk = params::DiskCreate {
2680+
identity: IdentityMetadataCreateParams {
2681+
name: "disk1".parse().unwrap(),
2682+
description: String::from("sells rainsticks"),
2683+
},
2684+
disk_backend: params::DiskBackend::Distributed {
2685+
disk_source: params::DiskSource::Blank {
2686+
block_size: params::BlockSize::try_from(512).unwrap(),
2687+
},
2688+
},
2689+
size: ByteCount::from_gibibytes_u32(1),
2690+
};
2691+
2692+
NexusRequest::new(
2693+
RequestBuilder::new(client, Method::POST, &disks_url)
2694+
.body(Some(&new_disk))
2695+
.expect_status(Some(StatusCode::CREATED)),
2696+
)
2697+
.authn_as(AuthnMode::PrivilegedUser)
2698+
.execute()
2699+
.await
2700+
.unwrap();
2701+
2702+
// Local disk
2703+
2704+
let new_disk = params::DiskCreate {
2705+
identity: IdentityMetadataCreateParams {
2706+
name: "disk2".parse().unwrap(),
2707+
description: String::from("sells rainsticks"),
2708+
},
2709+
disk_backend: params::DiskBackend::Local {},
2710+
size: ByteCount::from_gibibytes_u32(1),
2711+
};
2712+
2713+
NexusRequest::new(
2714+
RequestBuilder::new(client, Method::POST, &disks_url)
2715+
.body(Some(&new_disk))
2716+
.expect_status(Some(StatusCode::CREATED)),
2717+
)
2718+
.authn_as(AuthnMode::PrivilegedUser)
2719+
.execute()
2720+
.await
2721+
.unwrap();
2722+
2723+
// List them all
2724+
2725+
NexusRequest::new(
2726+
RequestBuilder::new(client, Method::GET, &disks_url)
2727+
.body(Some(&new_disk))
2728+
.expect_status(Some(StatusCode::OK)),
2729+
)
2730+
.authn_as(AuthnMode::PrivilegedUser)
2731+
.execute()
2732+
.await
2733+
.unwrap();
2734+
}
2735+
26612736
async fn disk_get(client: &ClientTestContext, disk_url: &str) -> Disk {
26622737
NexusRequest::object_get(client, disk_url)
26632738
.authn_as(AuthnMode::PrivilegedUser)

0 commit comments

Comments
 (0)