5
5
use super :: ActionRegistry ;
6
6
use super :: NexusActionContext ;
7
7
use super :: NexusSaga ;
8
- use super :: Params ;
9
8
use super :: STATE ;
10
9
use crate :: app:: sagas:: declare_saga_actions;
11
10
use crate :: app:: sagas:: ActionError ;
12
11
use nexus_db_model:: Generation ;
13
12
use nexus_db_model:: Instance ;
14
13
use nexus_db_model:: InstanceRuntimeState ;
15
14
use nexus_db_model:: Vmm ;
15
+ use nexus_db_queries:: authn;
16
+ use nexus_db_queries:: authz;
16
17
use nexus_db_queries:: db:: datastore:: InstanceAndVmms ;
17
18
use nexus_db_queries:: db:: identity:: Resource ;
18
19
use omicron_common:: api:: external;
19
20
use omicron_common:: api:: external:: Error ;
20
21
use omicron_common:: api:: external:: InstanceState ;
22
+ use serde:: { Deserialize , Serialize } ;
21
23
use slog:: info;
24
+ use uuid:: Uuid ;
22
25
23
- // instance update VMM destroyed subsaga: actions
26
+ // instance update (active VMM destroyed) subsaga: actions
24
27
25
28
// This subsaga is responsible for handling an instance update where the
26
29
// instance's active VMM has entered the `Destroyed` state. This requires
@@ -63,6 +66,21 @@ declare_saga_actions! {
63
66
}
64
67
}
65
68
69
+ /// Parameters to the instance update (active VMM destroyed) sub-saga.
70
+ #[ derive( Debug , Deserialize , Serialize ) ]
71
+ pub ( super ) struct Params {
72
+ /// Authentication context to use to fetch the instance's current state from
73
+ /// the database.
74
+ pub ( super ) serialized_authn : authn:: saga:: Serialized ,
75
+
76
+ pub ( super ) authz_instance : authz:: Instance ,
77
+
78
+ /// The UUID of the VMM that was destroyed.
79
+ pub ( super ) vmm_id : Uuid ,
80
+
81
+ pub ( super ) instance : Instance ,
82
+ }
83
+
66
84
#[ derive( Debug ) ]
67
85
pub ( crate ) struct SagaVmmDestroyed ;
68
86
impl NexusSaga for SagaVmmDestroyed {
@@ -104,14 +122,8 @@ fn get_destroyed_vmm(
104
122
async fn siud_release_sled_resources (
105
123
sagactx : NexusActionContext ,
106
124
) -> Result < ( ) , ActionError > {
107
- let Some ( ( _, vmm) ) = get_destroyed_vmm ( & sagactx) ? else {
108
- // if the update we are handling is not an active VMM destroyed update,
109
- // bail --- there's nothing to do here.
110
- return Ok ( ( ) ) ;
111
- } ;
112
-
113
125
let osagactx = sagactx. user_data ( ) ;
114
- let Params { ref serialized_authn, ref authz_instance } =
126
+ let Params { ref serialized_authn, ref authz_instance, vmm_id , .. } =
115
127
sagactx. saga_params :: < Params > ( ) ?;
116
128
117
129
let opctx =
@@ -121,13 +133,13 @@ async fn siud_release_sled_resources(
121
133
osagactx. log( ) ,
122
134
"instance update (active VMM destroyed): deallocating sled resource reservation" ;
123
135
"instance_id" => %authz_instance. id( ) ,
124
- "propolis_id" => %vmm . id ,
136
+ "propolis_id" => %vmm_id ,
125
137
"instance_update" => %"VMM destroyed" ,
126
138
) ;
127
139
128
140
osagactx
129
141
. datastore ( )
130
- . sled_reservation_delete ( & opctx, vmm . id )
142
+ . sled_reservation_delete ( & opctx, vmm_id )
131
143
. await
132
144
. or_else ( |err| {
133
145
// Necessary for idempotency
@@ -149,7 +161,7 @@ async fn siud_release_virtual_provisioning(
149
161
} ;
150
162
151
163
let osagactx = sagactx. user_data ( ) ;
152
- let Params { ref serialized_authn, ref authz_instance } =
164
+ let Params { ref serialized_authn, ref authz_instance, vmm_id , .. } =
153
165
sagactx. saga_params :: < Params > ( ) ?;
154
166
155
167
let opctx =
@@ -159,7 +171,7 @@ async fn siud_release_virtual_provisioning(
159
171
osagactx. log( ) ,
160
172
"instance update (VMM destroyed): deallocating virtual provisioning resources" ;
161
173
"instance_id" => %authz_instance. id( ) ,
162
- "propolis_id" => %vmm . id ,
174
+ "propolis_id" => %vmm_id ,
163
175
"instance_update" => %"VMM destroyed" ,
164
176
) ;
165
177
@@ -187,11 +199,6 @@ async fn siud_release_virtual_provisioning(
187
199
async fn siud_unassign_oximeter_producer (
188
200
sagactx : NexusActionContext ,
189
201
) -> Result < ( ) , ActionError > {
190
- let Some ( ( _, _) ) = get_destroyed_vmm ( & sagactx) ? else {
191
- // if the update we are handling is not an active VMM destroyed update,
192
- // bail --- there's nothing to do here.
193
- return Ok ( ( ) ) ;
194
- } ;
195
202
let osagactx = sagactx. user_data ( ) ;
196
203
let Params { ref serialized_authn, ref authz_instance, .. } =
197
204
sagactx. saga_params :: < Params > ( ) ?;
@@ -212,17 +219,15 @@ async fn siud_unassign_oximeter_producer(
212
219
async fn siud_delete_v2p_mappings (
213
220
sagactx : NexusActionContext ,
214
221
) -> Result < ( ) , ActionError > {
215
- let Some ( ( instance, vmm) ) = get_destroyed_vmm ( & sagactx) ? else {
216
- // if the update we are handling is not an active VMM destroyed update,
217
- // bail --- there's nothing to do here.
218
- return Ok ( ( ) ) ;
219
- } ;
222
+ let Params { ref authz_instance, vmm_id, .. } =
223
+ sagactx. saga_params :: < Params > ( ) ?;
224
+
220
225
let osagactx = sagactx. user_data ( ) ;
221
226
info ! (
222
227
osagactx. log( ) ,
223
228
"instance update (VMM destroyed): deleting V2P mappings" ;
224
- "instance_id" => %instance . id( ) ,
225
- "propolis_id" => %vmm . id ,
229
+ "instance_id" => %authz_instance . id( ) ,
230
+ "propolis_id" => %vmm_id ,
226
231
"instance_update" => %"VMM destroyed" ,
227
232
) ;
228
233
@@ -234,13 +239,8 @@ async fn siud_delete_v2p_mappings(
234
239
async fn siud_delete_nat_entries (
235
240
sagactx : NexusActionContext ,
236
241
) -> Result < ( ) , ActionError > {
237
- let Some ( ( _, vmm) ) = get_destroyed_vmm ( & sagactx) ? else {
238
- // if the update we are handling is not an active VMM destroyed update,
239
- // bail --- there's nothing to do here.
240
- return Ok ( ( ) ) ;
241
- } ;
242
242
let osagactx = sagactx. user_data ( ) ;
243
- let Params { ref serialized_authn, ref authz_instance, .. } =
243
+ let Params { ref serialized_authn, ref authz_instance, vmm_id , .. } =
244
244
sagactx. saga_params :: < Params > ( ) ?;
245
245
246
246
let opctx =
@@ -250,7 +250,7 @@ async fn siud_delete_nat_entries(
250
250
osagactx. log( ) ,
251
251
"instance update (VMM destroyed): deleting NAT entries" ;
252
252
"instance_id" => %authz_instance. id( ) ,
253
- "propolis_id" => %vmm . id ,
253
+ "propolis_id" => %vmm_id ,
254
254
"instance_update" => %"VMM destroyed" ,
255
255
) ;
256
256
@@ -265,11 +265,9 @@ async fn siud_delete_nat_entries(
265
265
async fn siud_update_instance (
266
266
sagactx : NexusActionContext ,
267
267
) -> Result < ( ) , ActionError > {
268
- let Some ( ( instance, vmm) ) = get_destroyed_vmm ( & sagactx) ? else {
269
- // if the update we are handling is not an active VMM destroyed update,
270
- // bail --- there's nothing to do here.
271
- return Ok ( ( ) ) ;
272
- } ;
268
+ let Params { ref authz_instance, ref vmm_id, instance, .. } =
269
+ sagactx. saga_params :: < Params > ( ) ?;
270
+
273
271
let osagactx = sagactx. user_data ( ) ;
274
272
let new_runtime = InstanceRuntimeState {
275
273
propolis_id : None ,
@@ -281,30 +279,25 @@ async fn siud_update_instance(
281
279
info ! (
282
280
osagactx. log( ) ,
283
281
"instance update (VMM destroyed): updating runtime state" ;
284
- "instance_id" => %instance . id( ) ,
285
- "propolis_id" => %vmm . id ,
282
+ "instance_id" => %authz_instance . id( ) ,
283
+ "propolis_id" => %vmm_id ,
286
284
"new_runtime_state" => ?new_runtime,
287
285
"instance_update" => %"VMM destroyed" ,
288
286
) ;
289
287
290
288
// It's okay for this to fail, it just means that the active VMM ID has changed.
291
289
let _ = osagactx
292
290
. datastore ( )
293
- . instance_update_runtime ( & instance . id ( ) , & new_runtime)
291
+ . instance_update_runtime ( & authz_instance . id ( ) , & new_runtime)
294
292
. await ;
295
293
Ok ( ( ) )
296
294
}
297
295
298
296
async fn siud_mark_vmm_deleted (
299
297
sagactx : NexusActionContext ,
300
298
) -> Result < ( ) , ActionError > {
301
- let Some ( ( instance, vmm) ) = get_destroyed_vmm ( & sagactx) ? else {
302
- // if the update we are handling is not an active VMM destroyed update,
303
- // bail --- there's nothing to do here.
304
- return Ok ( ( ) ) ;
305
- } ;
306
299
let osagactx = sagactx. user_data ( ) ;
307
- let Params { ref serialized_authn, .. } =
300
+ let Params { ref authz_instance , ref vmm_id , ref serialized_authn, .. } =
308
301
sagactx. saga_params :: < Params > ( ) ?;
309
302
310
303
let opctx =
@@ -313,14 +306,14 @@ async fn siud_mark_vmm_deleted(
313
306
info ! (
314
307
osagactx. log( ) ,
315
308
"instance update (VMM destroyed): marking VMM record deleted" ;
316
- "instance_id" => %instance . id( ) ,
317
- "propolis_id" => %vmm . id ,
309
+ "instance_id" => %authz_instance . id( ) ,
310
+ "propolis_id" => %vmm_id ,
318
311
"instance_update" => %"VMM destroyed" ,
319
312
) ;
320
313
321
314
osagactx
322
315
. datastore ( )
323
- . vmm_mark_deleted ( & opctx, & vmm . id )
316
+ . vmm_mark_deleted ( & opctx, vmm_id )
324
317
. await
325
318
. map ( |_| ( ) )
326
319
. map_err ( ActionError :: action_failed)
0 commit comments