77use super :: DataStore ;
88use super :: SQL_BATCH_SIZE ;
99use crate :: authz;
10+ use crate :: authz:: ApiResource ;
1011use crate :: context:: OpContext ;
1112use crate :: db:: collection_attach:: AttachError ;
1213use crate :: db:: collection_attach:: DatastoreAttachTarget ;
@@ -52,6 +53,7 @@ use omicron_common::api::external::Error;
5253use omicron_common:: api:: external:: IdentityMetadataCreateParams ;
5354use omicron_common:: api:: external:: ListResultVec ;
5455use omicron_common:: api:: external:: LookupResult ;
56+ use omicron_common:: api:: external:: LookupType ;
5557use omicron_common:: api:: external:: ResourceType ;
5658use omicron_common:: api:: external:: UpdateResult ;
5759use omicron_common:: api:: external:: http_pagination:: PaginatedBy ;
@@ -136,12 +138,14 @@ impl DataStore {
136138 instance_id : InstanceUuid ,
137139 pool_id : Uuid ,
138140 ) -> CreateResult < ExternalIp > {
141+ let silo_id = opctx. authn . silo_required ( ) ?. id ( ) ;
139142 let data = IncompleteExternalIp :: for_instance_source_nat (
140143 ip_id,
141144 instance_id. into_untyped_uuid ( ) ,
142145 pool_id,
146+ silo_id,
143147 ) ;
144- self . allocate_external_ip ( opctx, data) . await
148+ self . allocate_external_ip ( opctx, data, LookupType :: ById ( pool_id ) ) . await
145149 }
146150
147151 /// Create an Ephemeral IP address for a probe.
@@ -161,12 +165,15 @@ impl DataStore {
161165 ip_version,
162166 )
163167 . await ?;
168+ let silo_id = opctx. authn . silo_required ( ) ?. id ( ) ;
169+ let pool_lookup = authz_pool. lookup_type ( ) . clone ( ) ;
164170 let data = IncompleteExternalIp :: for_ephemeral_probe (
165171 ip_id,
166172 probe_id,
167173 authz_pool. id ( ) ,
174+ silo_id,
168175 ) ;
169- self . allocate_external_ip ( opctx, data) . await
176+ self . allocate_external_ip ( opctx, data, pool_lookup ) . await
170177 }
171178
172179 /// Create an Ephemeral IP address for an instance.
@@ -206,11 +213,17 @@ impl DataStore {
206213 )
207214 . await ?;
208215
209- let data = IncompleteExternalIp :: for_ephemeral ( ip_id, authz_pool. id ( ) ) ;
216+ let silo_id = opctx. authn . silo_required ( ) ?. id ( ) ;
217+ let pool_lookup = authz_pool. lookup_type ( ) . clone ( ) ;
218+ let data = IncompleteExternalIp :: for_ephemeral (
219+ ip_id,
220+ authz_pool. id ( ) ,
221+ silo_id,
222+ ) ;
210223
211224 // We might not be able to acquire a new IP, but in the event of an
212225 // idempotent or double attach this failure is allowed.
213- let temp_ip = self . allocate_external_ip ( opctx, data) . await ;
226+ let temp_ip = self . allocate_external_ip ( opctx, data, pool_lookup ) . await ;
214227 if let Err ( e) = temp_ip {
215228 // Use the pool's version for lookup when the request didn't
216229 // specify one. This handles the case where an explicit pool was
@@ -327,6 +340,7 @@ impl DataStore {
327340 "project_id" => %project_id,
328341 ) ;
329342
343+ let silo_id = opctx. authn . silo_required ( ) ?. id ( ) ;
330344 let data = if let Some ( ip) = explicit_ip {
331345 IncompleteExternalIp :: for_floating_explicit (
332346 ip_id,
@@ -335,6 +349,7 @@ impl DataStore {
335349 project_id,
336350 ip,
337351 authz_pool. id ( ) ,
352+ silo_id,
338353 )
339354 } else {
340355 IncompleteExternalIp :: for_floating (
@@ -343,29 +358,39 @@ impl DataStore {
343358 & identity. description ,
344359 project_id,
345360 authz_pool. id ( ) ,
361+ silo_id,
346362 )
347363 } ;
348364
349- self . allocate_external_ip ( opctx, data) . await
365+ let pool_lookup = authz_pool. lookup_type ( ) . clone ( ) ;
366+ self . allocate_external_ip ( opctx, data, pool_lookup) . await
350367 }
351368
352369 async fn allocate_external_ip (
353370 & self ,
354371 opctx : & OpContext ,
355372 data : IncompleteExternalIp ,
373+ pool_lookup : LookupType ,
356374 ) -> CreateResult < ExternalIp > {
357375 let conn = self . pool_connection_authorized ( opctx) . await ?;
358- let ip = Self :: allocate_external_ip_on_connection ( & conn, data)
359- . await
360- . map_err ( |err| err. into_public_ignore_retries ( ) ) ?;
376+ let ip =
377+ Self :: allocate_external_ip_on_connection ( & conn, data, pool_lookup)
378+ . await
379+ . map_err ( |err| err. into_public_ignore_retries ( ) ) ?;
361380 Ok ( ip)
362381 }
363382
364383 /// Variant of [Self::allocate_external_ip] which may be called from a
365384 /// transaction context.
385+ ///
386+ /// `pool_lookup` describes how the pool being allocated from was looked up
387+ /// originally. This is used to generate a correct error message when the
388+ /// pool isn't found or is no longer linked, which depends on how the API
389+ /// request specifed the pool in the first place.
366390 pub ( crate ) async fn allocate_external_ip_on_connection (
367391 conn : & async_bb8_diesel:: Connection < DbConnection > ,
368392 data : IncompleteExternalIp ,
393+ pool_lookup : LookupType ,
369394 ) -> Result < ExternalIp , TransactionError < Error > > {
370395 // Name needs to be cloned out here (if present) to give users a
371396 // sensible error message on name collision.
@@ -426,7 +451,10 @@ impl DataStore {
426451 ) )
427452 } else {
428453 TransactionError :: CustomError (
429- crate :: db:: queries:: external_ip:: from_diesel ( e) ,
454+ crate :: db:: queries:: external_ip:: from_diesel (
455+ e,
456+ pool_lookup. clone ( ) ,
457+ ) ,
430458 )
431459 }
432460 }
@@ -435,7 +463,10 @@ impl DataStore {
435463 return TransactionError :: Database ( e) ;
436464 }
437465 TransactionError :: CustomError (
438- crate :: db:: queries:: external_ip:: from_diesel ( e) ,
466+ crate :: db:: queries:: external_ip:: from_diesel (
467+ e,
468+ pool_lookup. clone ( ) ,
469+ ) ,
439470 )
440471 }
441472 }
@@ -460,7 +491,8 @@ impl DataStore {
460491 zone_id,
461492 zone_kind,
462493 ) ;
463- self . allocate_external_ip ( opctx, data) . await
494+ self . allocate_external_ip ( opctx, data, LookupType :: ById ( pool. id ( ) ) )
495+ . await
464496 }
465497
466498 /// Variant of [Self::external_ip_allocate_omicron_zone] which may be called
@@ -479,7 +511,12 @@ impl DataStore {
479511 zone_id,
480512 zone_kind,
481513 ) ;
482- Self :: allocate_external_ip_on_connection ( conn, data) . await
514+ Self :: allocate_external_ip_on_connection (
515+ conn,
516+ data,
517+ LookupType :: ById ( service_pool. id ( ) ) ,
518+ )
519+ . await
483520 }
484521
485522 /// List one page of all external IPs allocated to internal services
0 commit comments