@@ -120,6 +120,7 @@ use nexus_db_queries::db::datastore::CrucibleTargets;
120120use nexus_db_queries:: db:: datastore:: Disk ;
121121use nexus_db_queries:: db:: datastore:: InstanceAndActiveVmm ;
122122use nexus_db_queries:: db:: datastore:: InstanceStateComputer ;
123+ use nexus_db_queries:: db:: datastore:: LocalStorageDisk ;
123124use nexus_db_queries:: db:: datastore:: SQL_BATCH_SIZE ;
124125use nexus_db_queries:: db:: datastore:: VolumeCookedResult ;
125126use nexus_db_queries:: db:: datastore:: read_only_resources_associated_with_volume;
@@ -152,6 +153,7 @@ use omicron_common::api::external::MacAddr;
152153use omicron_uuid_kinds:: CollectionUuid ;
153154use omicron_uuid_kinds:: DatasetUuid ;
154155use omicron_uuid_kinds:: DownstairsRegionUuid ;
156+ use omicron_uuid_kinds:: ExternalZpoolUuid ;
155157use omicron_uuid_kinds:: GenericUuid ;
156158use omicron_uuid_kinds:: InstanceUuid ;
157159use omicron_uuid_kinds:: ParseError ;
@@ -2225,8 +2227,7 @@ async fn crucible_disk_info(
22252227 }
22262228 }
22272229 } else {
2228- // If the disk is not attached to anything, just print empty
2229- // fields.
2230+ // If the disk is not attached to anything, just print empty fields.
22302231 UpstairsRow {
22312232 host_serial : "-" . to_string ( ) ,
22322233 disk_name,
@@ -2286,6 +2287,141 @@ async fn crucible_disk_info(
22862287 Ok ( ( ) )
22872288}
22882289
2290+ async fn local_storage_disk_info (
2291+ opctx : & OpContext ,
2292+ datastore : & DataStore ,
2293+ disk : LocalStorageDisk ,
2294+ ) -> Result < ( ) , anyhow:: Error > {
2295+ #[ derive( Tabled ) ]
2296+ #[ tabled( rename_all = "SCREAMING_SNAKE_CASE" ) ]
2297+ struct GenericRow {
2298+ host_serial : String ,
2299+ disk_name : String ,
2300+ instance_name : String ,
2301+ propolis_zone : String ,
2302+ disk_state : String ,
2303+ }
2304+
2305+ let conn = datastore. pool_connection_for_tests ( ) . await ?;
2306+
2307+ let disk_name = disk. name ( ) . to_string ( ) ;
2308+ let disk_state = disk. runtime ( ) . disk_state . to_string ( ) ;
2309+
2310+ let row = if let Some ( instance_uuid) = disk. runtime ( ) . attach_instance_id {
2311+ // Get the instance this disk is attached to
2312+ use nexus_db_schema:: schema:: instance:: dsl as instance_dsl;
2313+ use nexus_db_schema:: schema:: vmm:: dsl as vmm_dsl;
2314+ let instances: Vec < InstanceAndActiveVmm > = instance_dsl:: instance
2315+ . filter ( instance_dsl:: id. eq ( instance_uuid) )
2316+ . left_join (
2317+ vmm_dsl:: vmm. on ( vmm_dsl:: id
2318+ . nullable ( )
2319+ . eq ( instance_dsl:: active_propolis_id)
2320+ . and ( vmm_dsl:: time_deleted. is_null ( ) ) ) ,
2321+ )
2322+ . limit ( 1 )
2323+ . select ( ( Instance :: as_select ( ) , Option :: < Vmm > :: as_select ( ) ) )
2324+ . load_async ( & * conn)
2325+ . await
2326+ . context ( "loading requested instance" ) ?
2327+ . into_iter ( )
2328+ . map ( |i : ( Instance , Option < Vmm > ) | i. into ( ) )
2329+ . collect ( ) ;
2330+
2331+ let Some ( instance) = instances. into_iter ( ) . next ( ) else {
2332+ bail ! ( "no instance: {} found" , instance_uuid) ;
2333+ } ;
2334+
2335+ let instance_name = instance. instance ( ) . name ( ) . to_string ( ) ;
2336+
2337+ if instance. vmm ( ) . is_some ( ) {
2338+ let propolis_id =
2339+ instance. instance ( ) . runtime ( ) . propolis_id . unwrap ( ) ;
2340+ let my_sled_id = instance. sled_id ( ) . unwrap ( ) ;
2341+
2342+ let ( _, my_sled) = LookupPath :: new ( opctx, datastore)
2343+ . sled_id ( my_sled_id)
2344+ . fetch ( )
2345+ . await
2346+ . context ( "failed to look up sled" ) ?;
2347+
2348+ GenericRow {
2349+ host_serial : my_sled. serial_number ( ) . to_string ( ) ,
2350+ disk_name,
2351+ instance_name,
2352+ propolis_zone : format ! ( "oxz_propolis-server_{}" , propolis_id) ,
2353+ disk_state,
2354+ }
2355+ } else {
2356+ GenericRow {
2357+ host_serial : NOT_ON_SLED_MSG . to_string ( ) ,
2358+ disk_name,
2359+ instance_name,
2360+ propolis_zone : NO_ACTIVE_PROPOLIS_MSG . to_string ( ) ,
2361+ disk_state,
2362+ }
2363+ }
2364+ } else {
2365+ // If the disk is not attached to anything, just print empty fields.
2366+ GenericRow {
2367+ host_serial : "-" . to_string ( ) ,
2368+ disk_name,
2369+ instance_name : "-" . to_string ( ) ,
2370+ propolis_zone : "-" . to_string ( ) ,
2371+ disk_state,
2372+ }
2373+ } ;
2374+
2375+ let table = tabled:: Table :: new ( vec ! [ row] )
2376+ . with ( tabled:: settings:: Style :: empty ( ) )
2377+ . with ( tabled:: settings:: Padding :: new ( 0 , 1 , 0 , 0 ) )
2378+ . to_string ( ) ;
2379+
2380+ println ! ( "{}" , table) ;
2381+
2382+ #[ derive( Tabled ) ]
2383+ #[ tabled( rename_all = "SCREAMING_SNAKE_CASE" ) ]
2384+ struct Row {
2385+ disk_name : String ,
2386+
2387+ time_created : DateTime < Utc > ,
2388+ #[ tabled( display_with = "display_option_blank" ) ]
2389+ time_deleted : Option < DateTime < Utc > > ,
2390+
2391+ dataset_id : DatasetUuid ,
2392+ pool_id : ExternalZpoolUuid ,
2393+ sled_id : SledUuid ,
2394+
2395+ dataset_size : u64 ,
2396+ }
2397+
2398+ if let Some ( allocation) = & disk. local_storage_dataset_allocation {
2399+ let rows = vec ! [ Row {
2400+ disk_name: disk. name( ) . to_string( ) ,
2401+
2402+ time_created: allocation. time_created,
2403+ time_deleted: allocation. time_deleted,
2404+
2405+ dataset_id: allocation. local_storage_dataset_id( ) ,
2406+ pool_id: allocation. pool_id( ) ,
2407+ sled_id: allocation. sled_id( ) ,
2408+
2409+ dataset_size: allocation. dataset_size. to_bytes( ) ,
2410+ } ] ;
2411+
2412+ let table = tabled:: Table :: new ( rows)
2413+ . with ( tabled:: settings:: Style :: empty ( ) )
2414+ . with ( tabled:: settings:: Padding :: new ( 0 , 1 , 0 , 0 ) )
2415+ . to_string ( ) ;
2416+
2417+ println ! ( "{}" , table) ;
2418+ } else {
2419+ println ! ( "no allocation yet" ) ;
2420+ }
2421+
2422+ Ok ( ( ) )
2423+ }
2424+
22892425/// Run `omdb db disk info <UUID>`.
22902426async fn cmd_db_disk_info (
22912427 opctx : & OpContext ,
@@ -2296,6 +2432,9 @@ async fn cmd_db_disk_info(
22962432 Disk :: Crucible ( disk) => {
22972433 crucible_disk_info ( opctx, datastore, disk) . await
22982434 }
2435+ Disk :: LocalStorage ( disk) => {
2436+ local_storage_disk_info ( opctx, datastore, disk) . await
2437+ }
22992438 }
23002439}
23012440
0 commit comments