|
29 | 29 | import org.zstack.header.tpm.entity.TpmVO_; |
30 | 30 | import org.zstack.header.vm.DiskAO; |
31 | 31 | import org.zstack.header.vm.PreVmInstantiateResourceExtensionPoint; |
| 32 | +import org.zstack.header.vm.VmInstanceConstant; |
32 | 33 | import org.zstack.header.vm.VmInstanceDestroyExtensionPoint; |
33 | 34 | import org.zstack.header.vm.VmInstanceInventory; |
34 | 35 | import org.zstack.header.vm.VmInstanceSpec; |
|
37 | 38 | import org.zstack.header.vm.VmPreMigrationExtensionPoint; |
38 | 39 | import org.zstack.header.vm.additions.VmHostBackupFileVO; |
39 | 40 | import org.zstack.header.vm.additions.VmHostBackupFileVO_; |
40 | | -import org.zstack.header.vm.additions.VmHostFileContentFormat; |
41 | 41 | import org.zstack.header.vm.additions.VmHostFileContentVO; |
42 | 42 | import org.zstack.header.vm.additions.VmHostFileContentVO_; |
43 | 43 | import org.zstack.header.vm.additions.VmHostFileType; |
|
70 | 70 | import javax.persistence.Tuple; |
71 | 71 | import java.sql.Timestamp; |
72 | 72 | import java.time.Instant; |
73 | | -import java.util.ArrayList; |
74 | 73 | import java.util.Base64; |
75 | 74 | import java.util.Collections; |
76 | 75 | import java.util.List; |
|
82 | 81 | import static org.zstack.header.vm.VmMigrationType.HostMigration; |
83 | 82 | import static org.zstack.kvm.KVMConstant.*; |
84 | 83 | import static org.zstack.utils.CollectionDSL.list; |
85 | | -import static org.zstack.utils.CollectionUtils.findOneOrNull; |
86 | | -import static org.zstack.utils.CollectionUtils.transform; |
87 | 84 |
|
88 | 85 | public class KvmSecureBootExtensions implements KVMStartVmExtensionPoint, |
89 | 86 | PreVmInstantiateResourceExtensionPoint, |
@@ -224,135 +221,6 @@ public void fail(ErrorCode errorCode) { |
224 | 221 | .start(); |
225 | 222 | } |
226 | 223 |
|
227 | | - public static class SyncVmHostFilesFromHostContext { |
228 | | - public String hostUuid; |
229 | | - public String vmUuid; |
230 | | - |
231 | | - public String nvRamPath; |
232 | | - public String tpmStateFolder; |
233 | | - } |
234 | | - |
235 | | - public void syncVmHostFilesFromHost(SyncVmHostFilesFromHostContext context, Completion completion) { |
236 | | - KvmCommandSender sender = new KvmCommandSender(context.hostUuid); |
237 | | - |
238 | | - ReadVmHostFileContentCmd cmd = new ReadVmHostFileContentCmd(); |
239 | | - cmd.setHostFiles(new ArrayList<>()); |
240 | | - if (context.tpmStateFolder != null) { |
241 | | - VmHostFileTO to = new VmHostFileTO(); |
242 | | - to.setPath(context.tpmStateFolder); |
243 | | - to.setType(VmHostFileType.TpmState.toString()); |
244 | | - cmd.getHostFiles().add(to); |
245 | | - } |
246 | | - if (context.nvRamPath != null) { |
247 | | - VmHostFileTO to = new VmHostFileTO(); |
248 | | - to.setPath(context.nvRamPath); |
249 | | - to.setType(VmHostFileType.NvRam.toString()); |
250 | | - cmd.getHostFiles().add(to); |
251 | | - } |
252 | | - |
253 | | - sender.send(cmd, READ_VM_HOST_FILE_PATH, wrapper -> { |
254 | | - ReadVmHostFileContentResponse readRsp = wrapper.getResponse(ReadVmHostFileContentResponse.class); |
255 | | - return readRsp.isSuccess() ? null : |
256 | | - operr("failed to read file content response").withException(readRsp.getError()); |
257 | | - }, new ReturnValueCompletion<KvmResponseWrapper>(completion) { |
258 | | - @Override |
259 | | - public void success(KvmResponseWrapper wrapper) { |
260 | | - ReadVmHostFileContentResponse readRsp = wrapper.getResponse(ReadVmHostFileContentResponse.class); |
261 | | - if (!readRsp.isSuccess()) { |
262 | | - completion.fail(operr("failed to read file content response").withException(readRsp.getError())); |
263 | | - return; |
264 | | - } |
265 | | - |
266 | | - final List<VmHostFileVO> existsFiles = Q.New(VmHostFileVO.class) |
267 | | - .eq(VmHostFileVO_.vmInstanceUuid, context.vmUuid) |
268 | | - .eq(VmHostFileVO_.hostUuid, context.hostUuid) |
269 | | - .in(VmHostFileVO_.path, cmd.getPaths()) |
270 | | - .list(); |
271 | | - final List<String> existsContentUuid; |
272 | | - if (!existsFiles.isEmpty()) { |
273 | | - existsContentUuid = Q.New(VmHostFileContentVO.class) |
274 | | - .in(VmHostFileContentVO_.uuid, transform(existsFiles, VmHostFileVO::getUuid)) |
275 | | - .select(VmHostFileContentVO_.uuid) |
276 | | - .listValues(); |
277 | | - } else { |
278 | | - existsContentUuid = Collections.emptyList(); |
279 | | - } |
280 | | - |
281 | | - List<ErrorCode> errors = new ArrayList<>(); |
282 | | - for (String path : cmd.getPaths()) { |
283 | | - VmHostFileTO to = findOneOrNull(readRsp.getHostFiles(), item -> item.getPath().equals(path)); |
284 | | - if (to == null) { |
285 | | - continue; |
286 | | - } |
287 | | - if (to.getError() != null) { |
288 | | - errors.add(operr("failed to read file %s", path) |
289 | | - .withOpaque("path", path) |
290 | | - .withException(to.getError())); |
291 | | - continue; |
292 | | - } |
293 | | - |
294 | | - VmHostFileType type = Objects.equals(path, context.nvRamPath) ? |
295 | | - VmHostFileType.NvRam : VmHostFileType.TpmState; |
296 | | - |
297 | | - VmHostFileVO file = findOneOrNull(existsFiles, item -> item.getPath().equals(path)); |
298 | | - boolean fileExists = file != null; |
299 | | - |
300 | | - Timestamp now = Timestamp.from(Instant.now()); |
301 | | - if (fileExists) { |
302 | | - SQL.New(VmHostFileVO.class) |
303 | | - .eq(VmHostFileVO_.uuid, file.getUuid()) |
304 | | - .set(VmHostFileVO_.lastOpDate, now) |
305 | | - .update(); |
306 | | - } else { |
307 | | - file = new VmHostFileVO(); |
308 | | - file.setUuid(Platform.getUuid()); |
309 | | - file.setHostUuid(context.hostUuid); |
310 | | - file.setVmInstanceUuid(context.vmUuid); |
311 | | - file.setPath(path); |
312 | | - file.setType(type); |
313 | | - file.setCreateDate(now); |
314 | | - file.setLastOpDate(now); |
315 | | - file.setResourceName(String.format("%s file for %s", type, context.vmUuid)); |
316 | | - databaseFacade.persist(file); |
317 | | - } |
318 | | - |
319 | | - byte[] bytes = Base64.getDecoder().decode(to.getContentBase64()); |
320 | | - if (existsContentUuid.contains(file.getUuid())) { |
321 | | - SQL.New(VmHostFileContentVO.class) |
322 | | - .eq(VmHostFileContentVO_.uuid, file.getUuid()) |
323 | | - .set(VmHostFileContentVO_.content, bytes) |
324 | | - .set(VmHostFileContentVO_.format, VmHostFileContentFormat.valueOf(to.getFileFormat())) |
325 | | - .set(VmHostFileContentVO_.lastOpDate, now) |
326 | | - .update(); |
327 | | - } else { |
328 | | - VmHostFileContentVO content = new VmHostFileContentVO(); |
329 | | - content.setUuid(file.getUuid()); |
330 | | - content.setContent(bytes); |
331 | | - content.setFormat(VmHostFileContentFormat.valueOf(to.getFileFormat())); |
332 | | - content.setCreateDate(now); |
333 | | - content.setLastOpDate(now); |
334 | | - databaseFacade.persist(content); |
335 | | - } |
336 | | - |
337 | | - if (logger.isTraceEnabled()) { |
338 | | - logger.trace(String.format("persist/update VmHostFileContentVO [uuid=%s]", file.getUuid())); |
339 | | - } |
340 | | - } |
341 | | - |
342 | | - if (errors.isEmpty()) { |
343 | | - completion.success(); |
344 | | - } else { |
345 | | - completion.fail(operr("failed to read file content from host[uuid=%s]", context.hostUuid).withCause(errors)); |
346 | | - } |
347 | | - } |
348 | | - |
349 | | - @Override |
350 | | - public void fail(ErrorCode errorCode) { |
351 | | - completion.fail(errorCode); |
352 | | - } |
353 | | - }); |
354 | | - } |
355 | | - |
356 | 224 | public static class RewriteVmHostFilesContext { |
357 | 225 | public String hostUuid; |
358 | 226 | public List<KVMAgentCommands.VmHostFileTO> hostFiles; |
@@ -517,29 +385,30 @@ public void run(FlowTrigger trigger, Map data) { |
517 | 385 | } |
518 | 386 |
|
519 | 387 | context.sameHost = vmHostFile.getHostUuid().equals(context.hostUuid); |
520 | | - SyncVmHostFilesFromHostContext syncContext = new SyncVmHostFilesFromHostContext(); |
521 | | - syncContext.hostUuid = vmHostFile.getHostUuid(); |
522 | | - syncContext.vmUuid = context.vmUuid; |
| 388 | + SyncVmHostFilesFromHostMsg syncMsg = new SyncVmHostFilesFromHostMsg(); |
| 389 | + syncMsg.setHostUuid(vmHostFile.getHostUuid()); |
| 390 | + syncMsg.setVmUuid(context.vmUuid); |
523 | 391 |
|
524 | 392 | if (vmHostFile.getType() == VmHostFileType.NvRam) { |
525 | | - context.path = syncContext.nvRamPath = vmHostFile.getPath(); |
| 393 | + context.path = vmHostFile.getPath(); |
| 394 | + syncMsg.setNvRamPath(context.path); |
526 | 395 | } else if (vmHostFile.getType() == VmHostFileType.TpmState) { |
527 | | - context.path = syncContext.tpmStateFolder = vmHostFile.getPath(); |
| 396 | + context.path = vmHostFile.getPath(); |
| 397 | + syncMsg.setTpmStateFolder(context.path); |
528 | 398 | } else { |
529 | 399 | throw new CloudRuntimeException("unsupported vm host file type: " + vmHostFile.getType()); |
530 | 400 | } |
531 | 401 |
|
532 | | - syncVmHostFilesFromHost(syncContext, new Completion(trigger) { |
533 | | - @Override |
534 | | - public void success() { |
535 | | - context.vmHostFile = vmHostFile; |
536 | | - trigger.next(); |
537 | | - } |
538 | | - |
| 402 | + bus.makeLocalServiceId(syncMsg, VmInstanceConstant.SECURE_BOOT_SERVICE_ID); |
| 403 | + bus.send(syncMsg, new CloudBusCallBack(trigger) { |
539 | 404 | @Override |
540 | | - public void fail(ErrorCode errorCode) { |
541 | | - logger.warn(String.format("failed to read vm host file for VM[vmUuid=%s] but still continue: %s", |
542 | | - context.vmUuid, errorCode.getReadableDetails())); |
| 405 | + public void run(MessageReply reply) { |
| 406 | + if (reply.isSuccess()) { |
| 407 | + context.vmHostFile = vmHostFile; |
| 408 | + } else { |
| 409 | + logger.warn(String.format("failed to read vm host file for VM[vmUuid=%s] but still continue: %s", |
| 410 | + context.vmUuid, reply.getError().getReadableDetails())); |
| 411 | + } |
543 | 412 | trigger.next(); |
544 | 413 | } |
545 | 414 | }); |
@@ -628,26 +497,25 @@ public boolean skip(Map data) { |
628 | 497 |
|
629 | 498 | @Override |
630 | 499 | public void run(FlowTrigger trigger, Map data) { |
631 | | - KvmSecureBootExtensions.SyncVmHostFilesFromHostContext syncBackContext = |
632 | | - new KvmSecureBootExtensions.SyncVmHostFilesFromHostContext(); |
633 | | - syncBackContext.hostUuid = context.hostUuid; |
634 | | - syncBackContext.vmUuid = context.vmUuid; |
| 500 | + SyncVmHostFilesFromHostMsg syncMsg = new SyncVmHostFilesFromHostMsg(); |
| 501 | + syncMsg.setHostUuid(context.hostUuid); |
| 502 | + syncMsg.setVmUuid(context.vmUuid); |
635 | 503 |
|
636 | 504 | if (context.type == VmHostFileType.NvRam) { |
637 | | - syncBackContext.nvRamPath = context.path; |
| 505 | + syncMsg.setNvRamPath(context.path); |
638 | 506 | } else if (context.type == VmHostFileType.TpmState) { |
639 | | - syncBackContext.tpmStateFolder = context.path; |
| 507 | + syncMsg.setTpmStateFolder(context.path); |
640 | 508 | } |
641 | 509 |
|
642 | | - syncVmHostFilesFromHost(syncBackContext, new Completion(trigger) { |
| 510 | + bus.makeLocalServiceId(syncMsg, VmInstanceConstant.SECURE_BOOT_SERVICE_ID); |
| 511 | + bus.send(syncMsg, new CloudBusCallBack(trigger) { |
643 | 512 | @Override |
644 | | - public void success() { |
645 | | - trigger.next(); |
646 | | - } |
647 | | - |
648 | | - @Override |
649 | | - public void fail(ErrorCode errorCode) { |
650 | | - trigger.fail(errorCode); |
| 513 | + public void run(MessageReply reply) { |
| 514 | + if (reply.isSuccess()) { |
| 515 | + trigger.next(); |
| 516 | + } else { |
| 517 | + trigger.fail(reply.getError()); |
| 518 | + } |
651 | 519 | } |
652 | 520 | }); |
653 | 521 | } |
|
0 commit comments