Skip to content

Commit a8f687b

Browse files
author
Zhang Wenhao
committed
<refactor>[kvm]: batch query VM host file content
* Optimize RestoreVmHostFileMsg handle method by batching database queries for VmHostFileContentVO to avoid N+1 query problem in loops * Add buildPathFor VmHostFileType helper method to unify path construction logic. Resolves: ZSV-11441 Related: ZSV-11310 Change-Id: I72726b67686471676f6b6b7977616e61636e6671
1 parent c60433b commit a8f687b

4 files changed

Lines changed: 47 additions & 42 deletions

File tree

plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.zstack.kvm;
22

33
import org.zstack.header.configuration.PythonClass;
4+
import org.zstack.header.exception.CloudRuntimeException;
45
import org.zstack.header.vm.VmInstanceState;
6+
import org.zstack.header.vm.additions.VmHostFileType;
57

68
@PythonClass
79
public interface KVMConstant {
@@ -209,6 +211,14 @@ public static String buildTpmStateFilePath(String vmUuid) {
209211
return String.format(TPM_STATE_FILE_PATH_FORMAT, vmUuidWithHyphen);
210212
}
211213

214+
public static String buildPathForVmHostFileType(VmHostFileType type, String vmUuid) {
215+
switch (type) {
216+
case NvRam: return buildNvramFilePath(vmUuid);
217+
case TpmState: return buildTpmStateFilePath(vmUuid);
218+
default: throw new CloudRuntimeException("unsupported VmHostFileType: " + type);
219+
}
220+
}
221+
212222
public static final String DHCP_BIN_FILE_PATH = "/usr/local/zstack/dnsmasq";
213223

214224
enum KvmVmState {

plugin/kvm/src/main/java/org/zstack/kvm/efi/KvmSecureBootExtensions.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,10 +440,7 @@ public void run(FlowTrigger trigger, Map data) {
440440
if (context.vmBackupFileVO != null) {
441441
logger.debug(String.format("use %s[type=%s] VM-host backup file for VM[uuid=%s]",
442442
context.vmBackupFileVO.getUuid(), context.type, context.vmUuid));
443-
switch (context.type) {
444-
case NvRam: context.path = buildNvramFilePath(context.vmUuid); break;
445-
case TpmState: context.path = buildTpmStateFilePath(context.vmUuid); break;
446-
}
443+
context.path = buildPathForVmHostFileType(context.type, context.vmUuid);
447444
}
448445
trigger.next();
449446
}

plugin/kvm/src/main/java/org/zstack/kvm/efi/KvmSecureBootManager.java

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,16 @@
6565
import java.util.Map;
6666
import java.util.Objects;
6767
import java.util.Set;
68+
import java.util.function.Function;
6869

6970
import static org.zstack.compute.vm.VmGlobalConfig.ENABLE_UEFI_SECURE_BOOT;
7071
import static org.zstack.compute.vm.VmGlobalConfig.RESET_TPM_AFTER_VM_CLONE;
7172
import static org.zstack.core.Platform.operr;
7273
import static org.zstack.kvm.KVMAgentCommands.*;
73-
import static org.zstack.kvm.KVMConstant.READ_VM_HOST_FILE_PATH;
74-
import static org.zstack.kvm.KVMConstant.WRITE_VM_HOST_FILE_PATH;
75-
import static org.zstack.kvm.KVMConstant.buildNvramFilePath;
76-
import static org.zstack.kvm.KVMConstant.buildTpmStateFilePath;
74+
import static org.zstack.kvm.KVMConstant.*;
7775
import static org.zstack.utils.CollectionDSL.list;
7876
import static org.zstack.utils.CollectionUtils.findOneOrNull;
77+
import static org.zstack.utils.CollectionUtils.toMap;
7978
import static org.zstack.utils.CollectionUtils.transform;
8079

8180
public class KvmSecureBootManager extends AbstractService {
@@ -619,6 +618,16 @@ private void handle(RestoreVmHostFileMsg msg) {
619618
return;
620619
}
621620

621+
// Batch query all backup file content before loop
622+
List<String> backupUuids = transform(backupFiles, VmHostBackupFileVO::getUuid);
623+
Map<String, VmHostFileContentVO> backupContentMap = new HashMap<>();
624+
if (!backupUuids.isEmpty()) {
625+
List<VmHostFileContentVO> backupContents = Q.New(VmHostFileContentVO.class)
626+
.in(VmHostFileContentVO_.uuid, backupUuids)
627+
.list();
628+
backupContentMap.putAll(toMap(backupContents, VmHostFileContentVO::getUuid, Function.identity()));
629+
}
630+
622631
List<VmHostFileTO> fileList = new ArrayList<>();
623632
for (VmHostFileType type : allTypes) {
624633
VmHostFileTO to = new VmHostFileTO();
@@ -630,21 +639,14 @@ private void handle(RestoreVmHostFileMsg msg) {
630639
if (hasBackupFile) {
631640
// Write operation
632641
VmHostBackupFileVO backupFile = backupFilesByType.get(type);
633-
VmHostFileContentVO content = Q.New(VmHostFileContentVO.class)
634-
.eq(VmHostFileContentVO_.uuid, backupFile.getUuid())
635-
.find();
642+
VmHostFileContentVO content = backupContentMap.get(backupFile.getUuid());
636643
if (content == null) {
637644
logger.warn(String.format("backup file content [uuid:%s] not found for type %s",
638645
backupFile.getUuid(), type));
639646
continue;
640647
}
641648

642-
if (type == VmHostFileType.NvRam) {
643-
to.setPath(buildNvramFilePath(msg.getVmInstanceUuid()));
644-
} else if (type == VmHostFileType.TpmState) {
645-
to.setPath(buildTpmStateFilePath(msg.getVmInstanceUuid()));
646-
}
647-
649+
to.setPath(buildPathForVmHostFileType(type, msg.getVmInstanceUuid()));
648650
to.setFileFormat(content.getFormat().toString());
649651
to.setOperation(VmHostFileOperation.Write.toString());
650652
String contentBase64 = Base64.getEncoder().encodeToString(content.getContent());
@@ -678,18 +680,12 @@ private void handle(RestoreVmHostFileMsg msg) {
678680
KVMAgentCommands.WriteVmHostFileContentResponse writeRsp = wrapper.getResponse(KVMAgentCommands.WriteVmHostFileContentResponse.class);
679681
return writeRsp.isSuccess() ? null :
680682
operr("failed to write/delete host file response").withException(writeRsp.getError());
681-
}, new ReturnValueCompletion<KvmResponseWrapper>(msg) {
683+
}, new ReturnValueCompletion<KvmResponseWrapper>(trigger) {
682684
@Override
683685
public void success(KvmResponseWrapper wrapper) {
684-
KVMAgentCommands.WriteVmHostFileContentResponse writeRsp = wrapper.getResponse(KVMAgentCommands.WriteVmHostFileContentResponse.class);
685-
if (writeRsp.isSuccess()) {
686-
logger.info(String.format("success to restore host files for VM[uuid:%s] from snapshot group[uuid:%s]",
687-
msg.getVmInstanceUuid(), msg.getSnapshotGroupUuid()));
688-
trigger.next();
689-
return;
690-
}
691-
trigger.fail(operr("failed to write/delete host file")
692-
.withException(writeRsp.getError()));
686+
logger.info(String.format("success to restore host files for VM[uuid:%s] from snapshot group[uuid:%s]",
687+
msg.getVmInstanceUuid(), msg.getSnapshotGroupUuid()));
688+
trigger.next();
693689
}
694690

695691
@Override
@@ -704,15 +700,25 @@ public void fail(ErrorCode errorCode) {
704700
.handle(trigger -> {
705701
Timestamp now = Timestamp.from(Instant.now());
706702

703+
List<String> allUuids = new ArrayList<>();
704+
allUuids.addAll(transform(backupFilesByType.values(), VmHostBackupFileVO::getUuid));
705+
allUuids.addAll(transform(currentFilesByType.values(), VmHostFileVO::getUuid));
706+
707+
Map<String, VmHostFileContentVO> contentMap = new HashMap<>();
708+
if (!allUuids.isEmpty()) {
709+
List<VmHostFileContentVO> contents = Q.New(VmHostFileContentVO.class)
710+
.in(VmHostFileContentVO_.uuid, allUuids)
711+
.list();
712+
contentMap.putAll(toMap(contents, VmHostFileContentVO::getUuid, Function.identity()));
713+
}
714+
707715
for (VmHostFileType type : allTypes) {
708716
boolean hasCurrentFile = currentFilesByType.containsKey(type);
709717
boolean hasBackupFile = backupFilesByType.containsKey(type);
710718

711719
if (hasBackupFile) {
712720
VmHostBackupFileVO backupFile = backupFilesByType.get(type);
713-
VmHostFileContentVO backupContent = Q.New(VmHostFileContentVO.class)
714-
.eq(VmHostFileContentVO_.uuid, backupFile.getUuid())
715-
.find();
721+
VmHostFileContentVO backupContent = contentMap.get(backupFile.getUuid());
716722
if (backupContent == null) {
717723
continue;
718724
}
@@ -725,9 +731,7 @@ public void fail(ErrorCode errorCode) {
725731
.set(VmHostFileVO_.lastOpDate, now)
726732
.update();
727733

728-
VmHostFileContentVO existingContent = Q.New(VmHostFileContentVO.class)
729-
.eq(VmHostFileContentVO_.uuid, currentFile.getUuid())
730-
.find();
734+
VmHostFileContentVO existingContent = contentMap.get(currentFile.getUuid());
731735
if (existingContent != null) {
732736
SQL.New(VmHostFileContentVO.class)
733737
.eq(VmHostFileContentVO_.uuid, currentFile.getUuid())
@@ -746,19 +750,13 @@ public void fail(ErrorCode errorCode) {
746750
}
747751
} else {
748752
// create new VmHostFileVO and VmHostFileContentVO
749-
String path;
750-
if (type == VmHostFileType.NvRam) {
751-
path = buildNvramFilePath(msg.getVmInstanceUuid());
752-
} else {
753-
path = buildTpmStateFilePath(msg.getVmInstanceUuid());
754-
}
755-
756753
VmHostFileVO newFile = new VmHostFileVO();
757754
newFile.setUuid(Platform.getUuid());
755+
newFile.setResourceName(String.format("%s file for %s", type, msg.getVmInstanceUuid()));
758756
newFile.setVmInstanceUuid(msg.getVmInstanceUuid());
759757
newFile.setHostUuid(finalHostUuid);
760758
newFile.setType(type);
761-
newFile.setPath(path);
759+
newFile.setPath(buildPathForVmHostFileType(type, msg.getVmInstanceUuid()));
762760
newFile.setCreateDate(now);
763761
newFile.setLastOpDate(now);
764762
databaseFacade.persist(newFile);

storage/src/main/java/org/zstack/storage/snapshot/group/VolumeSnapshotGroupBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ class Context {
405405
RestoreVmHostFileMsg restoreMsg = new RestoreVmHostFileMsg();
406406
restoreMsg.setVmInstanceUuid(vmUuid);
407407
restoreMsg.setSnapshotGroupUuid(self.getUuid());
408-
bus.makeTargetServiceIdByResourceUuid(restoreMsg, VmInstanceConstant.SECURE_BOOT_SERVICE_ID, vmUuid);
408+
bus.makeLocalServiceId(restoreMsg, VmInstanceConstant.SECURE_BOOT_SERVICE_ID);
409409
bus.send(restoreMsg, new CloudBusCallBack(trigger) {
410410
@Override
411411
public void run(MessageReply reply) {

0 commit comments

Comments
 (0)