Skip to content

Commit 7ab9254

Browse files
author
Zhang Wenhao
committed
<feature>[vm]: add TPM and NvRam restore support for snapshot group
* Add NvRamSpec class for NvRam device configuration. * Add backupFileUuid field to TpmSpec for TPM state restore. * Add nvRam field to VmDevicesSpec for NvRam device. * Create SnapshotGroupRevertTpmHelper to handle TPM and NvRam restore when creating VM from volume snapshot group. The helper queries backup files from VmHostBackupFileVO and sets the appropriate backupFileUuid to device specifications based on resetTpm parameter and available backup file types. Resolves: ZSV-11441 Related: ZSV-11310 Change-Id: I737a687a6f6f706565657a677779666e62656566
1 parent 67ca4a6 commit 7ab9254

4 files changed

Lines changed: 146 additions & 0 deletions

File tree

header/src/main/java/org/zstack/header/tpm/entity/TpmSpec.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public class TpmSpec {
99
private String keyProviderUuid;
1010
@APINoSee
1111
private String secretUuid;
12+
private String backupFileUuid;
1213
@APINoSee
1314
private boolean resourceKeyCreatedNew;
1415
@APINoSee
@@ -38,6 +39,14 @@ public void setKeyProviderUuid(String keyProviderUuid) {
3839
this.keyProviderUuid = keyProviderUuid;
3940
}
4041

42+
public String getBackupFileUuid() {
43+
return backupFileUuid;
44+
}
45+
46+
public void setBackupFileUuid(String backupFileUuid) {
47+
this.backupFileUuid = backupFileUuid;
48+
}
49+
4150
public String getSecretUuid() {
4251
return secretUuid;
4352
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.zstack.header.vm.devices;
2+
3+
public class NvRamSpec {
4+
private String backupFileUuid;
5+
6+
public String getBackupFileUuid() {
7+
return backupFileUuid;
8+
}
9+
10+
public void setBackupFileUuid(String backupFileUuid) {
11+
this.backupFileUuid = backupFileUuid;
12+
}
13+
}

header/src/main/java/org/zstack/header/vm/devices/VmDevicesSpec.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public class VmDevicesSpec {
77
* Default value of tpm must be null, because tpm.enable is true by default.
88
*/
99
private TpmSpec tpm;
10+
private NvRamSpec nvRam;
1011

1112
public TpmSpec getTpm() {
1213
return tpm;
@@ -16,6 +17,14 @@ public void setTpm(TpmSpec tpm) {
1617
this.tpm = tpm;
1718
}
1819

20+
public NvRamSpec getNvRam() {
21+
return nvRam;
22+
}
23+
24+
public void setNvRam(NvRamSpec nvRam) {
25+
this.nvRam = nvRam;
26+
}
27+
1928
public static VmDevicesSpec __example__() {
2029
VmDevicesSpec spec = new VmDevicesSpec();
2130
spec.setTpm(TpmSpec.__example__());
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package org.zstack.kvm.tpm;
2+
3+
import org.springframework.beans.factory.annotation.Autowire;
4+
import org.springframework.beans.factory.annotation.Autowired;
5+
import org.springframework.beans.factory.annotation.Configurable;
6+
import org.zstack.compute.vm.VmGlobalConfig;
7+
import org.zstack.core.db.Q;
8+
import org.zstack.header.storage.snapshot.group.VolumeSnapshotGroupVO;
9+
import org.zstack.header.storage.snapshot.group.VolumeSnapshotGroupVO_;
10+
import org.zstack.header.tpm.entity.TpmSpec;
11+
import org.zstack.header.vm.APICreateVmInstanceFromVolumeSnapshotGroupMsg;
12+
import org.zstack.header.vm.CreateVmInstanceMsg;
13+
import org.zstack.header.vm.additions.VmHostBackupFileVO;
14+
import org.zstack.header.vm.additions.VmHostBackupFileVO_;
15+
import org.zstack.header.vm.additions.VmHostFileType;
16+
import org.zstack.header.vm.devices.NvRamSpec;
17+
import org.zstack.header.vm.devices.VmDevicesSpec;
18+
import org.zstack.resourceconfig.ResourceConfigFacade;
19+
import org.zstack.utils.Utils;
20+
import org.zstack.utils.logging.CLogger;
21+
22+
import java.util.List;
23+
24+
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
25+
public class SnapshotGroupRevertTpmHelper {
26+
private static final CLogger logger = Utils.getLogger(SnapshotGroupRevertTpmHelper.class);
27+
28+
@Autowired
29+
ResourceConfigFacade resourceConfigFacade;
30+
31+
public void setupFromApi(APICreateVmInstanceFromVolumeSnapshotGroupMsg apiMsg, CreateVmInstanceMsg cmsg) {
32+
String snapshotGroupUuid = apiMsg.getVolumeSnapshotGroupUuid();
33+
34+
boolean resetTpm;
35+
if (apiMsg.getResetTpm() != null) {
36+
resetTpm = apiMsg.getResetTpm();
37+
} else {
38+
String vmInstanceUuid = Q.New(VolumeSnapshotGroupVO.class)
39+
.select(VolumeSnapshotGroupVO_.vmInstanceUuid)
40+
.eq(VolumeSnapshotGroupVO_.uuid, snapshotGroupUuid)
41+
.findValue();
42+
resetTpm = resourceConfigFacade.getResourceConfigValue(
43+
VmGlobalConfig.RESET_TPM_AFTER_VM_CLONE, vmInstanceUuid, Boolean.class);
44+
logger.debug(String.format("resetTpm not specified in API, resolved from resource config " +
45+
"RESET_TPM_AFTER_VM_CLONE for vm[uuid:%s]: %s", vmInstanceUuid, resetTpm));
46+
}
47+
48+
List<VmHostBackupFileVO> backupFiles = Q.New(VmHostBackupFileVO.class)
49+
.eq(VmHostBackupFileVO_.resourceUuid, snapshotGroupUuid)
50+
.list();
51+
52+
if (backupFiles.isEmpty()) {
53+
logger.debug(String.format(
54+
"no VmHostBackupFileVO found for volume snapshot group[uuid:%s], skip restoring TPM/NvRam",
55+
snapshotGroupUuid));
56+
return;
57+
}
58+
59+
VmHostBackupFileVO tpmBackupFile = null;
60+
VmHostBackupFileVO nvRamBackupFile = null;
61+
for (VmHostBackupFileVO f : backupFiles) {
62+
if (f.getType() == VmHostFileType.TpmState) {
63+
tpmBackupFile = f;
64+
} else if (f.getType() == VmHostFileType.NvRam) {
65+
nvRamBackupFile = f;
66+
}
67+
}
68+
69+
if (tpmBackupFile == null && nvRamBackupFile == null) {
70+
logger.debug(String.format("no TpmState or NvRam backup file found for volume snapshot group[uuid:%s]",
71+
snapshotGroupUuid));
72+
return;
73+
}
74+
75+
VmDevicesSpec devicesSpec = cmsg.getDevicesSpec();
76+
if (devicesSpec == null) {
77+
devicesSpec = new VmDevicesSpec();
78+
cmsg.setDevicesSpec(devicesSpec);
79+
}
80+
81+
if (tpmBackupFile != null) {
82+
TpmSpec tpmSpec = devicesSpec.getTpm();
83+
if (tpmSpec == null) {
84+
tpmSpec = new TpmSpec();
85+
devicesSpec.setTpm(tpmSpec);
86+
}
87+
tpmSpec.setEnable(true);
88+
89+
if (resetTpm) {
90+
// resetTpm=true: reset secretUuid, generate a new one during VM creation
91+
logger.debug(String.format("resetTpm is true for volume snapshot group[uuid:%s], " +
92+
"will reset secretUuid, tpmBackupFileUuid:%s", snapshotGroupUuid, tpmBackupFile.getUuid()));
93+
} else {
94+
tpmSpec.setBackupFileUuid(tpmBackupFile.getUuid());
95+
// resetTpm=false: should reuse secretUuid + keyProviderUuid recorded in VolumeSnapshotGroup,
96+
// but the recording step is not yet implemented, leave them empty for now
97+
// TODO: retrieve secretUuid and keyProviderUuid from VolumeSnapshotGroup and set them here
98+
logger.warn(String.format("resetTpm is false for volume snapshot group[uuid:%s], " +
99+
"should restore secretUuid and keyProviderUuid but they are not yet recorded in snapshot group, " +
100+
"leaving empty. tpmBackupFileUuid:%s", snapshotGroupUuid, tpmBackupFile.getUuid()));
101+
}
102+
}
103+
104+
if (nvRamBackupFile != null) {
105+
NvRamSpec nvRamSpec = devicesSpec.getNvRam();
106+
if (nvRamSpec == null) {
107+
nvRamSpec = new NvRamSpec();
108+
devicesSpec.setNvRam(nvRamSpec);
109+
}
110+
nvRamSpec.setBackupFileUuid(nvRamBackupFile.getUuid());
111+
logger.debug(String.format("set NvRam restore info for volume snapshot group[uuid:%s], nvRamBackupFileUuid:%s",
112+
snapshotGroupUuid, nvRamBackupFile.getUuid()));
113+
}
114+
}
115+
}

0 commit comments

Comments
 (0)