5
5
//! [`DataStore`] methods on Database Metadata.
6
6
7
7
use super :: { DataStore , DbConnection , IdentityCheckPolicy } ;
8
+ use crate :: authz;
9
+ use crate :: context:: OpContext ;
10
+
8
11
use anyhow:: { Context , bail, ensure} ;
9
12
use async_bb8_diesel:: { AsyncRunQueryDsl , AsyncSimpleConnection } ;
10
13
use chrono:: Utc ;
11
14
use diesel:: prelude:: * ;
15
+ use futures:: FutureExt ;
12
16
use nexus_db_errors:: ErrorHandler ;
13
17
use nexus_db_errors:: OptionalError ;
14
18
use nexus_db_errors:: public_error_from_diesel;
@@ -19,7 +23,9 @@ use nexus_db_model::DbMetadataNexusState;
19
23
use nexus_db_model:: EARLIEST_SUPPORTED_VERSION ;
20
24
use nexus_db_model:: SchemaUpgradeStep ;
21
25
use nexus_db_model:: SchemaVersion ;
26
+ use nexus_types:: deployment:: BlueprintZoneDisposition ;
22
27
use omicron_common:: api:: external:: Error ;
28
+ use omicron_uuid_kinds:: GenericUuid ;
23
29
use omicron_uuid_kinds:: OmicronZoneUuid ;
24
30
use semver:: Version ;
25
31
use slog:: { Logger , error, info, o} ;
@@ -701,6 +707,80 @@ impl DataStore {
701
707
Ok ( exists)
702
708
}
703
709
710
+ /// Deletes the "db_metadata_nexus" record for a Nexus ID, if it exists.
711
+ pub async fn database_nexus_access_delete (
712
+ & self ,
713
+ opctx : & OpContext ,
714
+ nexus_id : OmicronZoneUuid ,
715
+ ) -> Result < ( ) , Error > {
716
+ use nexus_db_schema:: schema:: db_metadata_nexus:: dsl;
717
+
718
+ opctx. authorize ( authz:: Action :: Modify , & authz:: FLEET ) . await ?;
719
+ let conn = & * self . pool_connection_authorized ( & opctx) . await ?;
720
+
721
+ diesel:: delete (
722
+ dsl:: db_metadata_nexus
723
+ . filter ( dsl:: nexus_id. eq ( nexus_id. into_untyped_uuid ( ) ) ) ,
724
+ )
725
+ . execute_async ( & * conn)
726
+ . await
727
+ . map_err ( |e| public_error_from_diesel ( e, ErrorHandler :: Server ) ) ?;
728
+
729
+ Ok ( ( ) )
730
+ }
731
+
732
+ /// Propagate the nexus records to the database if and only if
733
+ /// the blueprint is the current target.
734
+ ///
735
+ /// If any of these records already exist, they are unmodified.
736
+ pub async fn database_nexus_access_create (
737
+ & self ,
738
+ opctx : & OpContext ,
739
+ blueprint : & nexus_types:: deployment:: Blueprint ,
740
+ ) -> Result < ( ) , Error > {
741
+ opctx. authorize ( authz:: Action :: Modify , & authz:: FLEET ) . await ?;
742
+
743
+ // TODO: Without https://github.com/oxidecomputer/omicron/pull/8863, we
744
+ // treat all Nexuses as active. Some will become "not_yet", depending on
745
+ // the Nexus Generation, once it exists.
746
+ let active_nexus_zones = blueprint
747
+ . all_omicron_zones ( BlueprintZoneDisposition :: is_in_service)
748
+ . filter_map ( |( _sled, zone_cfg) | {
749
+ if zone_cfg. zone_type . is_nexus ( ) {
750
+ Some ( zone_cfg)
751
+ } else {
752
+ None
753
+ }
754
+ } ) ;
755
+ let new_nexuses = active_nexus_zones
756
+ . map ( |z| DbMetadataNexus :: new ( z. id , DbMetadataNexusState :: Active ) )
757
+ . collect :: < Vec < _ > > ( ) ;
758
+
759
+ let conn = & * self . pool_connection_authorized ( & opctx) . await ?;
760
+ self . transaction_if_current_blueprint_is (
761
+ & conn,
762
+ "database_nexus_access_create" ,
763
+ opctx,
764
+ blueprint. id ,
765
+ |conn| {
766
+ let new_nexuses = new_nexuses. clone ( ) ;
767
+ async move {
768
+ use nexus_db_schema:: schema:: db_metadata_nexus:: dsl;
769
+
770
+ diesel:: insert_into ( dsl:: db_metadata_nexus)
771
+ . values ( new_nexuses)
772
+ . on_conflict ( dsl:: nexus_id)
773
+ . do_nothing ( )
774
+ . execute_async ( & * conn)
775
+ . await ?;
776
+ Ok ( ( ) )
777
+ }
778
+ . boxed ( )
779
+ } ,
780
+ )
781
+ . await
782
+ }
783
+
704
784
// Registers a Nexus instance as having active access to the database
705
785
#[ cfg( test) ]
706
786
async fn database_nexus_access_insert (
0 commit comments