|
4 | 4 | import org.springframework.beans.factory.annotation.Autowired; |
5 | 5 | import org.zstack.compute.vm.VmGlobalConfig; |
6 | 6 | import org.zstack.compute.vm.devices.TpmEncryptedResourceKeyBackend; |
| 7 | +import org.zstack.compute.vm.devices.TpmEncryptedResourceKeyBackend.CloneEncryptedResourceKeyContext; |
7 | 8 | import org.zstack.core.Platform; |
8 | 9 | import org.zstack.core.cloudbus.CloudBus; |
9 | 10 | import org.zstack.core.cloudbus.CloudBusCallBack; |
|
15 | 16 | import org.zstack.header.core.Completion; |
16 | 17 | import org.zstack.header.core.workflow.FlowDoneHandler; |
17 | 18 | import org.zstack.header.core.workflow.FlowErrorHandler; |
| 19 | +import org.zstack.header.core.workflow.Flow; |
| 20 | +import org.zstack.header.core.workflow.FlowRollback; |
18 | 21 | import org.zstack.header.core.workflow.FlowTrigger; |
19 | 22 | import org.zstack.header.core.workflow.NoRollbackFlow; |
20 | 23 | import org.zstack.header.errorcode.ErrorCode; |
|
24 | 27 | import org.zstack.header.keyprovider.EncryptedResourceKeyManager.GetOrCreateResourceKeyContext; |
25 | 28 | import org.zstack.header.keyprovider.EncryptedResourceKeyManager.ResourceKeyResult; |
26 | 29 | import org.zstack.header.secret.SecretHostDefineMsg; |
| 30 | +import org.zstack.header.storage.snapshot.group.VolumeSnapshotGroupVO; |
| 31 | +import org.zstack.header.storage.snapshot.group.VolumeSnapshotGroupVO_; |
27 | 32 | import org.zstack.header.tpm.entity.TpmSpec; |
28 | 33 | import org.zstack.header.tpm.entity.TpmVO; |
| 34 | +import org.zstack.header.tpm.entity.TpmVO_; |
29 | 35 | import org.zstack.header.secret.SecretHostDefineReply; |
30 | 36 | import org.zstack.header.vm.PreVmInstantiateResourceExtensionPoint; |
31 | 37 | import org.zstack.header.vm.VmInstanceSpec; |
32 | 38 | import org.zstack.header.vm.VmInstantiateResourceException; |
| 39 | +import org.zstack.header.vm.additions.VmHostBackupFileVO; |
| 40 | +import org.zstack.header.vm.additions.VmHostBackupFileVO_; |
33 | 41 | import org.zstack.header.vm.additions.VmHostFileType; |
34 | 42 | import org.zstack.header.vm.additions.VmHostFileVO; |
35 | 43 | import org.zstack.header.vm.additions.VmHostFileVO_; |
@@ -167,6 +175,53 @@ public void fail(ErrorCode errorCode) { |
167 | 175 | } |
168 | 176 | }); |
169 | 177 | } |
| 178 | + }).then(new Flow() { |
| 179 | + String __name__ = "clone-tpm-resource-key-from-snapshot-source"; |
| 180 | + |
| 181 | + @Override |
| 182 | + public boolean skip(Map data) { |
| 183 | + return StringUtils.isBlank(findSourceTpmUuidFromSnapshotTpmBackupFile(context.backupFileUuid)) || |
| 184 | + VmGlobalConfig.ALLOWED_TPM_VM_WITHOUT_KMS.value(Boolean.class); |
| 185 | + } |
| 186 | + |
| 187 | + @Override |
| 188 | + public void run(FlowTrigger trigger, Map data) { |
| 189 | + String srcTpmUuid = findSourceTpmUuidFromSnapshotTpmBackupFile(context.backupFileUuid); |
| 190 | + if (StringUtils.isBlank(srcTpmUuid)) { |
| 191 | + trigger.next(); |
| 192 | + return; |
| 193 | + } |
| 194 | + CloneEncryptedResourceKeyContext cloneCtx = new CloneEncryptedResourceKeyContext(); |
| 195 | + cloneCtx.srcTpmUuid = srcTpmUuid; |
| 196 | + cloneCtx.dstTpmUuid = context.tpmUuid; |
| 197 | + cloneCtx.resetTpm = false; |
| 198 | + resourceKeyBackend.cloneEncryptedResourceKey(cloneCtx, new Completion(trigger) { |
| 199 | + @Override |
| 200 | + public void success() { |
| 201 | + context.providerUuid = resourceKeyBackend.findKeyProviderUuidByTpm(context.tpmUuid); |
| 202 | + context.providerName = resourceKeyBackend.findKeyProviderNameByTpm(context.tpmUuid); |
| 203 | + trigger.next(); |
| 204 | + } |
| 205 | + |
| 206 | + @Override |
| 207 | + public void fail(ErrorCode errorCode) { |
| 208 | + trigger.fail(errorCode); |
| 209 | + } |
| 210 | + }); |
| 211 | + } |
| 212 | + |
| 213 | + @Override |
| 214 | + public void rollback(FlowRollback trigger, Map data) { |
| 215 | + if (StringUtils.isNotBlank(context.backupFileUuid)) { |
| 216 | + try { |
| 217 | + resourceKeyBackend.detachKeyProviderFromTpm(context.tpmUuid); |
| 218 | + } catch (Exception e) { |
| 219 | + logger.warn(String.format("failed to detach key provider ref for tpm[uuid:%s]: %s", |
| 220 | + context.tpmUuid, e.getMessage())); |
| 221 | + } |
| 222 | + } |
| 223 | + trigger.rollback(); |
| 224 | + } |
170 | 225 | }).then(new NoRollbackFlow() { |
171 | 226 | String __name__ = "create-dek"; |
172 | 227 |
|
@@ -325,4 +380,28 @@ private void clearRollbackInfo(VmInstanceSpec spec) { |
325 | 380 | spec.getDevicesSpec().getTpm().setResourceKeyCreatedNew(false); |
326 | 381 | spec.getDevicesSpec().getTpm().setResourceKeyProviderUuid(null); |
327 | 382 | } |
| 383 | + |
| 384 | + private String findSourceTpmUuidFromSnapshotTpmBackupFile(String tpmBackupFileUuid) { |
| 385 | + if (StringUtils.isBlank(tpmBackupFileUuid)) { |
| 386 | + return null; |
| 387 | + } |
| 388 | + VmHostBackupFileVO bf = Q.New(VmHostBackupFileVO.class) |
| 389 | + .eq(VmHostBackupFileVO_.uuid, tpmBackupFileUuid) |
| 390 | + .eq(VmHostBackupFileVO_.type, VmHostFileType.TpmState) |
| 391 | + .find(); |
| 392 | + if (bf == null || StringUtils.isBlank(bf.getResourceUuid())) { |
| 393 | + return null; |
| 394 | + } |
| 395 | + String sourceVmUuid = Q.New(VolumeSnapshotGroupVO.class) |
| 396 | + .select(VolumeSnapshotGroupVO_.vmInstanceUuid) |
| 397 | + .eq(VolumeSnapshotGroupVO_.uuid, bf.getResourceUuid()) |
| 398 | + .findValue(); |
| 399 | + if (StringUtils.isBlank(sourceVmUuid)) { |
| 400 | + return null; |
| 401 | + } |
| 402 | + return Q.New(TpmVO.class) |
| 403 | + .eq(TpmVO_.vmInstanceUuid, sourceVmUuid) |
| 404 | + .select(TpmVO_.uuid) |
| 405 | + .findValue(); |
| 406 | + } |
328 | 407 | } |
0 commit comments