5353import org .zstack .header .vm .additions .VmHostFileType ;
5454import org .zstack .header .vm .additions .VmHostFileVO ;
5555import org .zstack .header .vm .additions .VmHostFileVO_ ;
56+ import org .zstack .header .vm .additions .VmHostFileOperation ;
57+ import org .zstack .header .core .ReturnValueCompletion ;
58+ import org .zstack .kvm .KVMConstant ;
59+ import org .zstack .kvm .KVMAgentCommands ;
60+ import org .zstack .kvm .KvmCommandSender ;
61+ import org .zstack .kvm .KvmResponseWrapper ;
5662import org .zstack .kvm .tpm .message .CloneVmTpmMsg ;
5763import org .zstack .kvm .tpm .message .CloneVmTpmReply ;
5864import org .zstack .resourceconfig .ResourceConfig ;
6268import org .zstack .utils .logging .CLogger ;
6369
6470import java .util .ArrayList ;
65- import java .util .HashSet ;
71+ import java .util .HashMap ;
6672import java .util .List ;
6773import java .util .Map ;
68- import java .util .Set ;
6974
7075import static org .zstack .compute .vm .VmGlobalConfig .RESET_TPM_AFTER_VM_CLONE ;
7176import static org .zstack .core .Platform .err ;
@@ -294,6 +299,7 @@ public String getName() {
294299 static class RemoveTpmFromVmContext {
295300 String vmInstanceUuid ;
296301 String tpmUuid ;
302+ List <VmHostFileVO > hostFiles ;
297303
298304 static RemoveTpmFromVmContext valueOf (RemoveTpmMsg msg ) {
299305 RemoveTpmFromVmContext context = new RemoveTpmFromVmContext ();
@@ -320,36 +326,85 @@ private void removeTpmFromVm(RemoveTpmFromVmContext context, Completion completi
320326 trigger .next ();
321327 })
322328 .build ())
329+ .then (Flow .of ("collect-vm-host-files" )
330+ .handle (trigger -> {
331+ // DO NOT delete NvRam type VmHostFile: Maybe secure boot or other component related.
332+ context .hostFiles = Q .New (VmHostFileVO .class )
333+ .eq (VmHostFileVO_ .vmInstanceUuid , context .vmInstanceUuid )
334+ .eq (VmHostFileVO_ .type , VmHostFileType .TpmState )
335+ .list ();
336+ trigger .next ();
337+ })
338+ .build ())
339+ .then (Flow .of ("send-delete-commands-to-hosts" )
340+ .skipIf (data -> context .hostFiles .isEmpty ())
341+ .handle (trigger -> {
342+ Map <String , List <VmHostFileVO >> filesByHost = new HashMap <>();
343+ for (VmHostFileVO file : context .hostFiles ) {
344+ filesByHost .computeIfAbsent (file .getHostUuid (), k -> new ArrayList <>()).add (file );
345+ }
346+
347+ new While <>(filesByHost .entrySet ()).each ((entry , whileCompletion ) -> {
348+ String hostUuid = entry .getKey ();
349+ List <VmHostFileVO > files = entry .getValue ();
350+
351+ KVMAgentCommands .WriteVmHostFileContentCmd cmd = new KVMAgentCommands .WriteVmHostFileContentCmd ();
352+ List <KVMAgentCommands .VmHostFileTO > fileTOs = new ArrayList <>();
353+ for (VmHostFileVO file : files ) {
354+ KVMAgentCommands .VmHostFileTO to = new KVMAgentCommands .VmHostFileTO ();
355+ to .setPath (file .getPath ());
356+ to .setType (file .getType ().toString ());
357+ to .setOperation (VmHostFileOperation .Delete .toString ());
358+ fileTOs .add (to );
359+ }
360+ cmd .setHostFiles (fileTOs );
361+
362+ new KvmCommandSender (hostUuid ).send (cmd , KVMConstant .WRITE_VM_HOST_FILE_PATH , wrapper -> {
363+ KVMAgentCommands .WriteVmHostFileContentResponse rsp =
364+ wrapper .getResponse (KVMAgentCommands .WriteVmHostFileContentResponse .class );
365+ return rsp .isSuccess () ? null : operr ("failed to delete host files on host[uuid=%s]" , hostUuid );
366+ }, new ReturnValueCompletion <KvmResponseWrapper >(whileCompletion ) {
367+ @ Override
368+ public void success (KvmResponseWrapper wrapper ) {
369+ whileCompletion .done ();
370+ }
371+
372+ @ Override
373+ public void fail (ErrorCode errorCode ) {
374+ logger .warn (String .format ("failed to delete host files on host[uuid=%s], but continuing with DB cleanup: %s" ,
375+ hostUuid , errorCode .getDetails ()));
376+ whileCompletion .done ();
377+ }
378+ });
379+ }).run (new WhileDoneCompletion (trigger ) {
380+ @ Override
381+ public void done (ErrorCodeList errorCodeList ) {
382+ trigger .next ();
383+ }
384+ });
385+ })
386+ .build ())
323387 .then (Flow .of ("detach-resource-key" )
324388 .handle (trigger -> {
325389 tpmKeyBackend .detachKeyProviderFromTpm (context .tpmUuid );
326390 trigger .next ();
327391 })
328392 .build ())
329- .then (Flow .of ("remove-tpm- db-records" )
393+ .then (Flow .of ("remove-db-records" )
330394 .handle (trigger -> {
331395 new SQLBatch () {
332396 @ Override
333397 protected void scripts () {
334- Set <VmHostFileType > types = new HashSet <>();
335- types .add (VmHostFileType .TpmState );
336-
337398 sql (TpmVO .class )
338399 .eq (TpmVO_ .uuid , context .tpmUuid )
339400 .delete ();
340-
341- boolean needRegisterNvRam = vmTpmManager .needRegisterNvRam (context .vmInstanceUuid );
342- if (!needRegisterNvRam ) {
343- types .add (VmHostFileType .NvRam );
344- }
345-
346401 sql (VmHostFileVO .class )
347402 .eq (VmHostFileVO_ .vmInstanceUuid , context .vmInstanceUuid )
348- .in (VmHostFileVO_ .type , types )
403+ .eq (VmHostFileVO_ .type , VmHostFileType . TpmState )
349404 .delete ();
350405 sql (VmHostBackupFileVO .class )
351406 .eq (VmHostBackupFileVO_ .resourceUuid , context .vmInstanceUuid )
352- .in (VmHostBackupFileVO_ .type , types )
407+ .eq (VmHostBackupFileVO_ .type , VmHostFileType . TpmState )
353408 .delete ();
354409 }
355410 }.execute ();
0 commit comments