6060import org .zstack .utils .logging .CLogger ;
6161
6262import java .util .ArrayList ;
63+ import java .util .HashSet ;
6364import java .util .List ;
6465import java .util .Map ;
66+ import java .util .Set ;
6567
6668import static org .zstack .compute .vm .VmGlobalConfig .RESET_TPM_AFTER_VM_CLONE ;
6769import static org .zstack .core .Platform .err ;
@@ -189,6 +191,10 @@ static class AddTpmToVmContext {
189191 String vmInstanceUuid ;
190192 String tpmUuid ;
191193
194+ boolean tpmCreated ;
195+ boolean keyProviderAttached ;
196+ String createdTpmUuid ;
197+
192198 static AddTpmToVmContext valueOf (AddTpmMsg msg ) {
193199 AddTpmToVmContext context = new AddTpmToVmContext ();
194200 context .keyProviderUuid = msg .getKeyProviderUuid ();
@@ -198,46 +204,55 @@ static AddTpmToVmContext valueOf(AddTpmMsg msg) {
198204 }
199205 }
200206
201- @ SuppressWarnings ("rawtypes" )
202207 private void addTpmToVm (AddTpmToVmContext context , Completion completion ) {
203- SimpleFlowChain chain = new SimpleFlowChain ();
204- chain .setName ("add-tpm-to-vm-" + context .vmInstanceUuid );
205- chain .then (new NoRollbackFlow () {
206- String __name__ = "check-vm-status" ;
207-
208- @ Override
209- public void run (FlowTrigger trigger , Map data ) {
210- VmInstanceVO vm = Q .New (VmInstanceVO .class )
211- .eq (VmInstanceVO_ .uuid , context .vmInstanceUuid )
212- .find ();
213-
214- if (!SUPPORT_VM_STATES_FOR_TPM_OPERATION .contains (vm .getState ())) {
215- trigger .fail (err (VM_STATE_ERROR ,
216- "The current VM state does not support adding TPM operations" )
217- .withOpaque ("support.vm.state" , SUPPORT_VM_STATES_FOR_TPM_OPERATION ));
218- return ;
219- }
220- trigger .next ();
221- }
222- }).then (new NoRollbackFlow () {
223- String __name__ = "create-tpm-db-records" ;
224-
225- @ Override
226- public void run (FlowTrigger trigger , Map data ) {
227- vmTpmManager .persistTpmVO (context .tpmUuid , context .vmInstanceUuid );
228- trigger .next ();
229- }
230- }).done (new FlowDoneHandler (completion ) {
231- @ Override
232- public void handle (Map data ) {
233- completion .success ();
234- }
235- }).error (new FlowErrorHandler (completion ) {
236- @ Override
237- public void handle (ErrorCode errorCode , Map data ) {
238- completion .fail (errorCode );
239- }
240- }).start ();
208+ SimpleFlowChain .of ("add-tpm-to-vm-" + context .vmInstanceUuid )
209+ .then (Flow .of ("check-vm-status" )
210+ .handle (trigger -> {
211+ VmInstanceVO vm = Q .New (VmInstanceVO .class )
212+ .eq (VmInstanceVO_ .uuid , context .vmInstanceUuid )
213+ .find ();
214+
215+ if (!SUPPORT_VM_STATES_FOR_TPM_OPERATION .contains (vm .getState ())) {
216+ trigger .fail (err (VM_STATE_ERROR ,
217+ "The current VM state does not support adding TPM operations" )
218+ .withOpaque ("support.vm.state" , SUPPORT_VM_STATES_FOR_TPM_OPERATION ));
219+ return ;
220+ }
221+ trigger .next ();
222+ })
223+ .build ())
224+ .then (Flow .of ("create-tpm-db-records" )
225+ .handle (trigger -> {
226+ try {
227+ TpmVO tpm = vmTpmManager .persistTpmVO (context .tpmUuid , context .vmInstanceUuid );
228+ context .createdTpmUuid = tpm .getUuid ();
229+ context .tpmCreated = true ;
230+ if (context .keyProviderUuid != null ) {
231+ tpmKeyBackend .attachKeyProviderToTpm (context .createdTpmUuid , context .keyProviderUuid );
232+ context .keyProviderAttached = true ;
233+ }
234+ trigger .next ();
235+ } catch (Exception e ) {
236+ trigger .fail (operr ("failed to add TPM to vm[uuid:%s]: %s" , context .vmInstanceUuid , e .getMessage ()));
237+ }
238+ })
239+ .rollback (trigger -> {
240+ try {
241+ if (context .keyProviderAttached && context .createdTpmUuid != null ) {
242+ tpmKeyBackend .detachKeyProviderFromTpm (context .createdTpmUuid );
243+ }
244+ } finally {
245+ if (context .tpmCreated && context .createdTpmUuid != null ) {
246+ vmTpmManager .deleteTpmVO (context .createdTpmUuid );
247+ }
248+ }
249+ trigger .rollback ();
250+ })
251+ .build ())
252+ .propagateExceptionTo (completion )
253+ .done (completion ::success )
254+ .error (completion ::fail )
255+ .start ();
241256 }
242257
243258 private void handle (RemoveTpmMsg msg ) {
@@ -286,48 +301,63 @@ static RemoveTpmFromVmContext valueOf(RemoveTpmMsg msg) {
286301 }
287302 }
288303
289- @ SuppressWarnings ("rawtypes" )
290304 private void removeTpmFromVm (RemoveTpmFromVmContext context , Completion completion ) {
291- SimpleFlowChain chain = new SimpleFlowChain ();
292- chain .setName ("remove-tpm-from-vm-" + context .vmInstanceUuid );
293- chain .then (new NoRollbackFlow () {
294- String __name__ = "check-vm-status" ;
295-
296- @ Override
297- public void run (FlowTrigger trigger , Map data ) {
298- VmInstanceVO vm = Q .New (VmInstanceVO .class )
299- .eq (VmInstanceVO_ .uuid , context .vmInstanceUuid )
300- .find ();
301-
302- if (!SUPPORT_VM_STATES_FOR_TPM_OPERATION .contains (vm .getState ())) {
303- trigger .fail (err (VM_STATE_ERROR ,
304- "The current VM state does not support removing TPM operations" )
305- .withOpaque ("support.vm.state" , SUPPORT_VM_STATES_FOR_TPM_OPERATION ));
306- return ;
307- }
308- trigger .next ();
309- }
310- }).then (new NoRollbackFlow () {
311- String __name__ = "remove-tpm-db-records" ;
312-
313- @ Override
314- public void run (FlowTrigger trigger , Map data ) {
315- SQL .New (TpmVO .class )
316- .eq (TpmVO_ .uuid , context .tpmUuid )
317- .delete ();
318- trigger .next ();
319- }
320- }).done (new FlowDoneHandler (completion ) {
321- @ Override
322- public void handle (Map data ) {
323- completion .success ();
324- }
325- }).error (new FlowErrorHandler (completion ) {
326- @ Override
327- public void handle (ErrorCode errorCode , Map data ) {
328- completion .fail (errorCode );
329- }
330- }).start ();
305+ SimpleFlowChain .of ("remove-tpm-from-vm-" + context .vmInstanceUuid )
306+ .then (Flow .of ("check-vm-status" )
307+ .handle (trigger -> {
308+ VmInstanceVO vm = Q .New (VmInstanceVO .class )
309+ .eq (VmInstanceVO_ .uuid , context .vmInstanceUuid )
310+ .find ();
311+
312+ if (!SUPPORT_VM_STATES_FOR_TPM_OPERATION .contains (vm .getState ())) {
313+ trigger .fail (err (VM_STATE_ERROR ,
314+ "The current VM state does not support removing TPM operations" )
315+ .withOpaque ("support.vm.state" , SUPPORT_VM_STATES_FOR_TPM_OPERATION ));
316+ return ;
317+ }
318+ trigger .next ();
319+ })
320+ .build ())
321+ .then (Flow .of ("detach-resource-key" )
322+ .handle (trigger -> {
323+ tpmKeyBackend .detachKeyProviderFromTpm (context .tpmUuid );
324+ trigger .next ();
325+ })
326+ .build ())
327+ .then (Flow .of ("remove-tpm-db-records" )
328+ .handle (trigger -> {
329+ new SQLBatch () {
330+ @ Override
331+ protected void scripts () {
332+ Set <VmHostFileType > types = new HashSet <>();
333+ types .add (VmHostFileType .TpmState );
334+
335+ sql (TpmVO .class )
336+ .eq (TpmVO_ .uuid , context .tpmUuid )
337+ .delete ();
338+
339+ boolean needRegisterNvRam = vmTpmManager .needRegisterNvRam (context .vmInstanceUuid );
340+ if (!needRegisterNvRam ) {
341+ types .add (VmHostFileType .NvRam );
342+ }
343+
344+ sql (VmHostFileVO .class )
345+ .eq (VmHostFileVO_ .vmInstanceUuid , context .vmInstanceUuid )
346+ .in (VmHostFileVO_ .type , types )
347+ .delete ();
348+ sql (VmHostBackupFileVO .class )
349+ .eq (VmHostBackupFileVO_ .resourceUuid , context .vmInstanceUuid )
350+ .in (VmHostBackupFileVO_ .type , types )
351+ .delete ();
352+ }
353+ }.execute ();
354+ trigger .next ();
355+ })
356+ .build ())
357+ .propagateExceptionTo (completion )
358+ .done (completion ::success )
359+ .error (completion ::fail )
360+ .start ();
331361 }
332362
333363 @ SuppressWarnings ("rawtypes" )
0 commit comments