Skip to content

Commit 339a604

Browse files
author
Zhang Wenhao
committed
<feature>[kvm]: sync VM host files after migration
Add VmInstanceMigrateExtensionPoint to KvmSecureBootExtensions. In afterMigrateVm, clean up stale VmHostFileVO/VmHostFileContentVO on dest host first, then sync host files (NvRam/TpmState) from the dest host using src host records as path reference. Errors are tolerated to avoid blocking the migration flow. Resolves: ZSV-11438 Related: ZSV-11310 Change-Id: I6a7375747776657a63756a7072796570647a6a64
1 parent 237c737 commit 339a604

3 files changed

Lines changed: 70 additions & 1 deletion

File tree

conf/springConfigXml/Kvm.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@
274274
<zstack:extension interface="org.zstack.header.vm.VmPreMigrationExtensionPoint" />
275275
<zstack:extension interface="org.zstack.header.vm.AfterReimageVmInstanceExtensionPoint" />
276276
<zstack:extension interface="org.zstack.header.vm.VmReleaseResourceExtensionPoint" />
277+
<zstack:extension interface="org.zstack.header.vm.VmInstanceMigrateExtensionPoint" />
277278
</zstack:plugin>
278279
</bean>
279280
</beans>

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

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.zstack.core.db.SQL;
1414
import org.zstack.core.workflow.SimpleFlowChain;
1515
import org.zstack.header.core.Completion;
16+
import org.zstack.header.core.NoErrorCompletion;
1617
import org.zstack.header.core.ReturnValueCompletion;
1718
import org.zstack.header.core.workflow.Flow;
1819
import org.zstack.header.core.workflow.FlowDoneHandler;
@@ -33,6 +34,7 @@
3334
import org.zstack.header.vm.AfterReimageVmInstanceExtensionPoint;
3435
import org.zstack.header.vm.VmInstanceDestroyExtensionPoint;
3536
import org.zstack.header.vm.VmInstanceInventory;
37+
import org.zstack.header.vm.VmInstanceMigrateExtensionPoint;
3638
import org.zstack.header.vm.VmInstanceSpec;
3739
import org.zstack.header.vm.VmInstantiateResourceException;
3840
import org.zstack.header.vm.VmMigrationType;
@@ -89,7 +91,8 @@ public class KvmSecureBootExtensions implements KVMStartVmExtensionPoint,
8991
VmInstanceDestroyExtensionPoint,
9092
VmPreMigrationExtensionPoint,
9193
AfterReimageVmInstanceExtensionPoint,
92-
VmReleaseResourceExtensionPoint {
94+
VmReleaseResourceExtensionPoint,
95+
VmInstanceMigrateExtensionPoint {
9396
private static final CLogger logger = Utils.getLogger(KvmSecureBootExtensions.class);
9497

9598
@Autowired
@@ -780,4 +783,68 @@ public void run(MessageReply reply) {
780783
}
781784
});
782785
}
786+
787+
@Override
788+
public void afterMigrateVm(VmInstanceInventory inv, String srcHostUuid, NoErrorCompletion completion) {
789+
String destHostUuid = inv.getHostUuid();
790+
String vmUuid = inv.getUuid();
791+
792+
List<VmHostFileVO> vmHostFiles = Q.New(VmHostFileVO.class)
793+
.eq(VmHostFileVO_.vmInstanceUuid, vmUuid)
794+
.eq(VmHostFileVO_.hostUuid, srcHostUuid)
795+
.list();
796+
if (vmHostFiles.isEmpty()) {
797+
completion.done();
798+
return;
799+
}
800+
801+
// clean up stale VmHostFileVO/VmHostFileContentVO on dest host
802+
// before sync creates new records
803+
List<VmHostFileVO> staleFiles = Q.New(VmHostFileVO.class)
804+
.eq(VmHostFileVO_.vmInstanceUuid, vmUuid)
805+
.eq(VmHostFileVO_.hostUuid, destHostUuid)
806+
.list();
807+
if (!staleFiles.isEmpty()) {
808+
List<String> staleUuids = staleFiles.stream()
809+
.map(VmHostFileVO::getUuid)
810+
.collect(java.util.stream.Collectors.toList());
811+
SQL.New(VmHostFileContentVO.class)
812+
.in(VmHostFileContentVO_.uuid, staleUuids)
813+
.delete();
814+
SQL.New(VmHostFileVO.class)
815+
.in(VmHostFileVO_.uuid, staleUuids)
816+
.delete();
817+
logger.debug(String.format("cleaned up %d stale VmHostFileVO/Content on dest host[uuid=%s] for VM[uuid=%s]",
818+
staleFiles.size(), destHostUuid, vmUuid));
819+
}
820+
821+
logger.info(String.format("sync VM host file[vmUuid=%s] from dest host[uuid=%s] after migration",
822+
vmUuid, destHostUuid));
823+
SyncVmHostFilesFromHostMsg syncMsg = new SyncVmHostFilesFromHostMsg();
824+
syncMsg.setHostUuid(destHostUuid);
825+
syncMsg.setVmUuid(vmUuid);
826+
827+
for (VmHostFileVO file : vmHostFiles) {
828+
if (file.getType() == VmHostFileType.NvRam) {
829+
syncMsg.setNvRamPath(file.getPath());
830+
} else if (file.getType() == VmHostFileType.TpmState) {
831+
syncMsg.setTpmStateFolder(file.getPath());
832+
} else {
833+
logger.warn(String.format("unsupported vm host file type: %s, skip syncing for VM[uuid:%s]",
834+
file.getType(), vmUuid));
835+
}
836+
}
837+
838+
bus.makeLocalServiceId(syncMsg, VmInstanceConstant.SECURE_BOOT_SERVICE_ID);
839+
bus.send(syncMsg, new CloudBusCallBack(completion) {
840+
@Override
841+
public void run(MessageReply reply) {
842+
if (!reply.isSuccess()) {
843+
logger.warn(String.format("failed to sync VM host file[vmUuid=%s] from host[uuid=%s] after migration, but tolerated: %s",
844+
vmUuid, destHostUuid, reply.getError().getReadableDetails()));
845+
}
846+
completion.done();
847+
}
848+
});
849+
}
783850
}

test/src/test/resources/springConfigXml/Kvm.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@
273273
<zstack:extension interface="org.zstack.header.vm.VmPreMigrationExtensionPoint" />
274274
<zstack:extension interface="org.zstack.header.vm.AfterReimageVmInstanceExtensionPoint" />
275275
<zstack:extension interface="org.zstack.header.vm.VmReleaseResourceExtensionPoint" />
276+
<zstack:extension interface="org.zstack.header.vm.VmInstanceMigrateExtensionPoint" />
276277
</zstack:plugin>
277278
</bean>
278279
</beans>

0 commit comments

Comments
 (0)