Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package org.zstack.compute.vm.devices;

import org.springframework.beans.factory.annotation.Autowired;
import org.zstack.compute.vm.BuildVmSpecExtensionPoint;
import org.zstack.header.vm.CreateVmInstanceMsg;
import org.zstack.header.vm.DiskAO;
import org.zstack.header.vm.VmInstanceCreateExtensionPoint;
import org.zstack.header.vm.VmInstanceSpec;
import org.zstack.header.vm.VmInstanceVO;
import org.zstack.header.vm.devices.VmDevicesSpec;

public class VmTpmExtensions implements VmInstanceCreateExtensionPoint {
import static org.zstack.header.vm.VmInstanceConstant.NVRAM_DEFAULT_SIZE;

public class VmTpmExtensions implements VmInstanceCreateExtensionPoint,
BuildVmSpecExtensionPoint {
@Autowired
private VmTpmManager vmTpmManager;

Expand All @@ -24,4 +30,17 @@ public void afterPersistVmInstanceVO(VmInstanceVO vo, CreateVmInstanceMsg msg) {

vmTpmManager.persistTpmVO(null, vo.getUuid());
}

@Override
public void afterBuildVmSpec(VmInstanceSpec spec) {
String vmUuid = spec.getVmInventory().getUuid();
if (!vmTpmManager.needRegisterNvram(vmUuid)) {
return;
}

DiskAO nvramSpec = new DiskAO();
nvramSpec.setSize(NVRAM_DEFAULT_SIZE);
nvramSpec.setName("nvram-of-VM-" + vmUuid);
spec.setNvRamSpec(nvramSpec);
Comment on lines 41 to 44
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

rootSpec 可能为 null,需要防御性检查。

spec.getRootDisk() 在某些边缘情况下可能返回 null(例如 VM 规格尚未完全构建时)。如果 rootSpec 为 null,line 44 调用 rootSpec.getPrimaryStorageUuid() 会导致 NullPointerException。

🛡️ 建议修复
         DiskAO nvramSpec = new DiskAO();
         DiskAO rootSpec = spec.getRootDisk();
         // nvram always use root disk's primary storage
-        nvramSpec.setPrimaryStorageUuid(rootSpec.getPrimaryStorageUuid()); // may be null
+        if (rootSpec != null) {
+            nvramSpec.setPrimaryStorageUuid(rootSpec.getPrimaryStorageUuid());
+        }
         nvramSpec.setSize(NVRAM_DEFAULT_SIZE);
         nvramSpec.setName("nvram-of-VM-" + vmUuid);
         spec.setNvRamSpec(nvramSpec);
🤖 Prompt for AI Agents
In `@compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java`
around lines 41 - 47, The code assumes spec.getRootDisk() is non-null; add a
defensive null check for rootSpec before calling
rootSpec.getPrimaryStorageUuid() in the block that builds nvramSpec (DiskAO
nvramSpec, DiskAO rootSpec, nvramSpec.setPrimaryStorageUuid(...),
spec.setNvRamSpec(...)). If rootSpec is null, set
nvramSpec.setPrimaryStorageUuid(null) or otherwise avoid dereferencing rootSpec
(e.g., leave primaryStorageUuid unset or use a safe fallback), then continue to
set size/name and call spec.setNvRamSpec(nvramSpec).

}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
package org.zstack.compute.vm.devices;

import org.springframework.beans.factory.annotation.Autowired;
import org.zstack.compute.vm.VmSystemTags;
import org.zstack.core.Platform;
import org.zstack.core.db.DatabaseFacade;
import org.zstack.core.db.Q;
import org.zstack.header.image.ImageBootMode;
import org.zstack.header.tpm.entity.TpmVO;
import org.zstack.header.tpm.entity.TpmVO_;
import org.zstack.resourceconfig.ResourceConfig;
import org.zstack.resourceconfig.ResourceConfigFacade;
import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;

import java.util.Objects;

import static org.zstack.compute.vm.VmGlobalConfig.ENABLE_UEFI_SECURE_BOOT;

public class VmTpmManager {
private static final CLogger logger = Utils.getLogger(VmTpmManager.class);

@Autowired
private DatabaseFacade databaseFacade;
@Autowired
private ResourceConfigFacade resourceConfigFacade;

public TpmVO persistTpmVO(String tpmUuid, String vmUuid) {
if (tpmUuid == null) {
Expand All @@ -26,4 +38,29 @@ public TpmVO persistTpmVO(String tpmUuid, String vmUuid) {
logger.debug("Persisted TpmVO for VM " + vmUuid + " with uuid=" + tpm.getUuid());
return tpm;
}

public boolean needRegisterNvram(String vmUuid) {
boolean tpmExists = Q.New(TpmVO.class)
.eq(TpmVO_.vmInstanceUuid, vmUuid)
.isExists();
if (tpmExists) {
return true;
}

String bootMode = VmSystemTags.BOOT_MODE.getTokenByResourceUuid(vmUuid, VmSystemTags.BOOT_MODE_TOKEN);
if (!isUefiBootMode(bootMode)) {
return false;
}

ResourceConfig resourceConfig = resourceConfigFacade.getResourceConfig(ENABLE_UEFI_SECURE_BOOT.getIdentity());
return resourceConfig.getResourceConfigValue(vmUuid, Boolean.class) == Boolean.TRUE;
}

/**
* @param bootMode boot mode, null is Legacy
*/
public static boolean isUefiBootMode(String bootMode) {
return Objects.equals(bootMode, ImageBootMode.UEFI.toString())
|| Objects.equals(bootMode, ImageBootMode.UEFI_WITH_CSM.toString());
}
}
2 changes: 2 additions & 0 deletions conf/persistence.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
<class>org.zstack.resourceconfig.ResourceConfigVO</class>
<class>org.zstack.header.managementnode.ManagementNodeVO</class>
<class>org.zstack.header.managementnode.ManagementNodeContextVO</class>
<class>org.zstack.header.tpm.entity.TpmHostRefVO</class>
<class>org.zstack.header.tpm.entity.TpmVO</class>
<class>org.zstack.header.zone.ZoneVO</class>
<class>org.zstack.header.zone.ZoneEO</class>
<class>org.zstack.header.cluster.ClusterVO</class>
Expand Down
1 change: 1 addition & 0 deletions conf/springConfigXml/Kvm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@
<bean id="KvmSecureBootExtensions" class="org.zstack.kvm.efi.KvmSecureBootExtensions">
<zstack:plugin>
<zstack:extension interface="org.zstack.kvm.KVMStartVmExtensionPoint" />
<zstack:extension interface="org.zstack.header.vm.PreVmInstantiateResourceExtensionPoint" />
</zstack:plugin>
</bean>
</beans>
1 change: 1 addition & 0 deletions conf/springConfigXml/VmInstanceManager.xml
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@
<bean id="VmTpmExtensions" class="org.zstack.compute.vm.devices.VmTpmExtensions">
<zstack:plugin>
<zstack:extension interface="org.zstack.header.vm.VmInstanceCreateExtensionPoint" />
<zstack:extension interface="org.zstack.compute.vm.BuildVmSpecExtensionPoint" />
</zstack:plugin>
</bean>
</beans>
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.zstack.header.vm;

import org.zstack.header.configuration.PythonClass;
import org.zstack.utils.data.SizeUnit;

@PythonClass
public interface VmInstanceConstant {
Expand All @@ -25,6 +26,8 @@ public interface VmInstanceConstant {
String SHUTDOWN_DETAIL_BY_GUEST = "by guest";
String SHUTDOWN_DETAIL_FINISHED = "finished";

long NVRAM_DEFAULT_SIZE = SizeUnit.MEGABYTE.toByte(1);

enum Params {
VmInstanceSpec,
AttachingVolumeInventory,
Expand Down
9 changes: 9 additions & 0 deletions header/src/main/java/org/zstack/header/vm/VmInstanceSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ public void setCandidatePrimaryStorageUuidsForDataVolume(List<String> candidateP
private List<DiskAO> deprecatedDisksSpecs = new ArrayList<>();
private VmCustomSpecificationStruct vmCustomSpecification;
private VmDevicesSpec devicesSpec;
private DiskAO nvRamSpec;

public DiskAO getRootDisk() {
return rootDisk;
Expand Down Expand Up @@ -446,6 +447,14 @@ public void setDevicesSpec(VmDevicesSpec devicesSpec) {
this.devicesSpec = devicesSpec;
}

public DiskAO getNvRamSpec() {
return nvRamSpec;
}

public void setNvRamSpec(DiskAO nvRamSpec) {
this.nvRamSpec = nvRamSpec;
}

public boolean isSkipIpAllocation() {
return skipIpAllocation;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ public enum VolumeType {
Root,
Data,
Memory,
Cache
Cache,
NVRAM,
}
9 changes: 9 additions & 0 deletions plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -2068,6 +2068,7 @@ public static class StartVmCmd extends vdiCmd implements VmAddOnsCmd {
private List<CdRomTO> cdRoms = new ArrayList<>();
private List<VolumeTO> dataVolumes;
private List<VolumeTO> cacheVolumes;
private VolumeTO nvRam;
private List<NicTO> nics;
private TpmTO tpm;
private long timeout;
Expand Down Expand Up @@ -2549,6 +2550,14 @@ public void setCacheVolumes(List<VolumeTO> cacheVolumes) {
this.cacheVolumes = cacheVolumes;
}

public VolumeTO getNvRam() {
return nvRam;
}

public void setNvRam(VolumeTO nvRam) {
this.nvRam = nvRam;
}

public List<NicTO> getNics() {
return nics;
}
Expand Down
Loading