|
12 | 12 | import org.zstack.compute.cluster.arch.ClusterResourceConfigInitializer; |
13 | 13 | import org.zstack.compute.host.*; |
14 | 14 | import org.zstack.compute.vm.*; |
| 15 | +import org.zstack.compute.vm.devices.TpmEncryptedResourceKeyBackend; |
| 16 | +import org.zstack.compute.vm.devices.VmTpmManager; |
15 | 17 | import org.zstack.core.asyncbatch.While; |
16 | 18 | import org.zstack.core.cloudbus.ResourceDestinationMaker; |
17 | 19 | import org.zstack.core.timeout.TimeHelper; |
|
55 | 57 | import org.zstack.header.exception.CloudRuntimeException; |
56 | 58 | import org.zstack.header.host.*; |
57 | 59 | import org.zstack.header.host.MigrateVmOnHypervisorMsg.StorageMigrationPolicy; |
| 60 | +import org.zstack.header.keyprovider.EncryptedResourceKeyManager; |
| 61 | +import org.zstack.header.keyprovider.EncryptedResourceKeyManager.GetOrCreateResourceKeyContext; |
| 62 | +import org.zstack.header.keyprovider.EncryptedResourceKeyManager.ResourceKeyResult; |
58 | 63 | import org.zstack.header.secret.SecretHostDefineMsg; |
59 | 64 | import org.zstack.header.secret.SecretHostDefineReply; |
60 | 65 | import org.zstack.header.message.APIMessage; |
|
68 | 73 | import org.zstack.header.rest.RESTFacade; |
69 | 74 | import org.zstack.header.storage.primary.*; |
70 | 75 | import org.zstack.header.tag.SystemTagInventory; |
| 76 | +import org.zstack.header.tpm.entity.TpmVO; |
71 | 77 | import org.zstack.header.vm.*; |
72 | 78 | import org.zstack.header.vm.devices.DeviceAddress; |
73 | 79 | import org.zstack.header.volume.*; |
@@ -164,6 +170,10 @@ public class KVMHost extends HostBase implements Host { |
164 | 170 | private AccountManager accountMgr; |
165 | 171 | @Autowired |
166 | 172 | private ResourceDestinationMaker destMaker; |
| 173 | + @Autowired |
| 174 | + private TpmEncryptedResourceKeyBackend tpmKeyBackend; |
| 175 | + @Autowired |
| 176 | + private EncryptedResourceKeyManager resourceKeyManager; |
167 | 177 |
|
168 | 178 | private KVMHostContext context; |
169 | 179 |
|
@@ -3162,6 +3172,89 @@ public void fail(ErrorCode errorCode) { |
3162 | 3172 | } |
3163 | 3173 | }); |
3164 | 3174 |
|
| 3175 | + flow(new Flow() { |
| 3176 | + String __name__ = "ensure-secret-on-dst-before-migrate"; |
| 3177 | + String ensuredTpmUuid; |
| 3178 | + |
| 3179 | + @Override |
| 3180 | + public void run(FlowTrigger trigger, Map data) { |
| 3181 | + String tpmUuid = VmTpmManager.findTpmUuidForVmOrNull(vmUuid); |
| 3182 | + if (StringUtils.isBlank(tpmUuid)) { |
| 3183 | + trigger.next(); |
| 3184 | + return; |
| 3185 | + } |
| 3186 | + ensuredTpmUuid = tpmUuid; |
| 3187 | + |
| 3188 | + String providerUuid = tpmKeyBackend.findKeyProviderUuidByTpm(tpmUuid); |
| 3189 | + String providerName = tpmKeyBackend.findKeyProviderNameByTpm(tpmUuid); |
| 3190 | + if (StringUtils.isBlank(providerUuid) && StringUtils.isBlank(providerName)) { |
| 3191 | + trigger.fail(operr("missing TPM resource key binding for tpm[uuid:%s] before migrate", tpmUuid)); |
| 3192 | + return; |
| 3193 | + } |
| 3194 | + |
| 3195 | + GetOrCreateResourceKeyContext keyCtx = new GetOrCreateResourceKeyContext(); |
| 3196 | + keyCtx.setResourceUuid(tpmUuid); |
| 3197 | + keyCtx.setResourceType(TpmVO.class.getSimpleName()); |
| 3198 | + keyCtx.setKeyProviderUuid(providerUuid); |
| 3199 | + keyCtx.setKeyProviderName(providerName); |
| 3200 | + keyCtx.setPurpose("vtpm"); |
| 3201 | + resourceKeyManager.getOrCreateKey(keyCtx, new ReturnValueCompletion<ResourceKeyResult>(trigger) { |
| 3202 | + @Override |
| 3203 | + public void success(ResourceKeyResult result) { |
| 3204 | + String effectiveProviderName = result.getKeyProviderName(); |
| 3205 | + if (StringUtils.isBlank(effectiveProviderName)) { |
| 3206 | + effectiveProviderName = providerName; |
| 3207 | + } |
| 3208 | + if (StringUtils.isBlank(effectiveProviderName)) { |
| 3209 | + trigger.fail(operr("missing effective key provider name for tpm[uuid:%s] before migrate", tpmUuid)); |
| 3210 | + return; |
| 3211 | + } |
| 3212 | + |
| 3213 | + SecretHostDefineMsg innerMsg = new SecretHostDefineMsg(); |
| 3214 | + innerMsg.setHostUuid(dstHostUuid); |
| 3215 | + innerMsg.setVmUuid(vmUuid); |
| 3216 | + innerMsg.setDekBase64(result.getDekBase64()); |
| 3217 | + innerMsg.setPurpose("vtpm"); |
| 3218 | + innerMsg.setProviderName(effectiveProviderName); |
| 3219 | + innerMsg.setDescription(String.format("Define secret for VM %s before live migration", vmUuid)); |
| 3220 | + bus.makeTargetServiceIdByResourceUuid(innerMsg, HostConstant.SERVICE_ID, innerMsg.getHostUuid()); |
| 3221 | + bus.send(innerMsg, new CloudBusCallBack(trigger) { |
| 3222 | + @Override |
| 3223 | + public void run(MessageReply reply) { |
| 3224 | + if (reply.isSuccess()) { |
| 3225 | + trigger.next(); |
| 3226 | + } else { |
| 3227 | + trigger.fail(reply.getError()); |
| 3228 | + } |
| 3229 | + } |
| 3230 | + }); |
| 3231 | + } |
| 3232 | + |
| 3233 | + @Override |
| 3234 | + public void fail(ErrorCode errorCode) { |
| 3235 | + trigger.fail(errorCode); |
| 3236 | + } |
| 3237 | + }); |
| 3238 | + } |
| 3239 | + |
| 3240 | + @Override |
| 3241 | + public void rollback(FlowRollback trigger, Map data) { |
| 3242 | + if (StringUtils.isBlank(ensuredTpmUuid)) { |
| 3243 | + trigger.rollback(); |
| 3244 | + return; |
| 3245 | + } |
| 3246 | + |
| 3247 | + try { |
| 3248 | + tpmKeyBackend.detachKeyProviderFromTpm(ensuredTpmUuid); |
| 3249 | + } catch (Throwable t) { |
| 3250 | + logger.warn(String.format("failed to detach key provider from tpm[uuid:%s] during migrate rollback, %s", |
| 3251 | + ensuredTpmUuid, t.getMessage()), t); |
| 3252 | + } |
| 3253 | + |
| 3254 | + trigger.rollback(); |
| 3255 | + } |
| 3256 | + }); |
| 3257 | + |
3165 | 3258 | flow(new NoRollbackFlow() { |
3166 | 3259 | String __name__ = "migrate-vm"; |
3167 | 3260 |
|
|
0 commit comments