Skip to content

Commit 7d650fb

Browse files
author
gitlab
committed
Merge branch 'zsv-ldap-3@@2' into 'feature-zsv-5.0.0-vm-support-vtpm-and-secuceboot'
<feature>[kvm]: add key provider binding to TPM operations See merge request zstackio/zstack!9468
2 parents a3e3214 + 99ae29b commit 7d650fb

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)