Skip to content

Commit 99ae29b

Browse files
author
Zhang Wenhao
committed
<feature>[kvm]: add key provider binding to TPM operations
Refactor addTpmToVm and removeTpmFromVm methods to use new Flow API and add key provider binding support. Changes: - Migrate from SimpleFlowChain to new Flow API with lambda - Add keyProvider attach in addTpmToVm flow - Add keyProvider detach in removeTpmFromVm flow - Add proper rollback handling for failures - Track TPM creation state in context for cleanup This ensures key provider is properly associated with TPM during creation and detached during removal, with proper error handling and resource cleanup. Resolves: ZSV-11489 Related: ZSV-11310 Related: ZSV-11617 Change-Id: I7064796e6a76656469716a6f686570686b6a7773
1 parent 130a9dd commit 99ae29b

1 file changed

Lines changed: 110 additions & 80 deletions

File tree

plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmManager.java

Lines changed: 110 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@
6060
import org.zstack.utils.logging.CLogger;
6161

6262
import java.util.ArrayList;
63+
import java.util.HashSet;
6364
import java.util.List;
6465
import java.util.Map;
66+
import java.util.Set;
6567

6668
import static org.zstack.compute.vm.VmGlobalConfig.RESET_TPM_AFTER_VM_CLONE;
6769
import 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

Comments
 (0)