restore with correct bios type

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
Abhishek Kumar 2026-03-18 14:24:57 +05:30
parent 3bce25db2b
commit 90d87d0e92
5 changed files with 101 additions and 30 deletions

View File

@ -178,6 +178,7 @@ import com.cloud.vm.UserVmVO;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDetailsDao;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
@ -239,6 +240,9 @@ public class ServerAdapter extends ManagerBase {
@Inject
UserVmJoinDao userVmJoinDao;
@Inject
VMInstanceDetailsDao vmInstanceDetailsDao;
@Inject
VolumeDao volumeDao;
@ -519,7 +523,7 @@ public class ServerAdapter extends ManagerBase {
public List<Vm> listAllInstances() {
List<UserVmJoinVO> vms = userVmJoinDao.listAll();
return UserVmJoinVOToVmConverter.toVmList(vms, this::getHostById);
return UserVmJoinVOToVmConverter.toVmList(vms, this::getHostById, this::getDetailsByInstanceId);
}
public Vm getInstance(String uuid, boolean includeDisks, boolean includeNics, boolean allContent) {
@ -528,6 +532,7 @@ public class ServerAdapter extends ManagerBase {
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
}
return UserVmJoinVOToVmConverter.toVm(vo, this::getHostById,
this::getDetailsByInstanceId,
includeDisks ? this::listDiskAttachmentsByInstanceId : null,
includeNics ? this::listNicsByInstance : null,
allContent);
@ -605,12 +610,7 @@ public class ServerAdapter extends ManagerBase {
if (request.getInitialization() != null) {
userdata = request.getInitialization().getCustomScript();
}
ApiConstants.BootType bootType = ApiConstants.BootType.BIOS;
ApiConstants.BootMode bootMode = ApiConstants.BootMode.LEGACY;
if (request.getBios() != null && StringUtils.isNotEmpty(request.getBios().getType()) && request.getBios().getType().contains("secure")) {
bootType = ApiConstants.BootType.UEFI;
bootMode = ApiConstants.BootMode.SECURE;
}
Pair<ApiConstants.BootType, ApiConstants.BootMode> bootOptions = Vm.Bios.retrieveBootOptions(request.getBios());
Ternary<Long, String, Long> owner = getVmOwner(request);
String serviceOfferingUuid = null;
if (request.getCpuProfile() != null && StringUtils.isNotEmpty(request.getCpuProfile().getId())) {
@ -624,7 +624,7 @@ public class ServerAdapter extends ManagerBase {
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
try {
return createInstance(zoneId, clusterId, owner.first(), owner.second(), owner.third(), name, displayName,
serviceOfferingUuid, cpu, memory, templateUuid, userdata, bootType, bootMode);
serviceOfferingUuid, cpu, memory, templateUuid, userdata, bootOptions.first(), bootOptions.second());
} finally {
CallContext.unregister();
}
@ -714,8 +714,8 @@ public class ServerAdapter extends ManagerBase {
UserVm vm = userVmService.createVirtualMachine(cmd);
vm = userVmService.finalizeCreateVirtualMachine(vm.getId());
UserVmJoinVO vo = userVmJoinDao.findById(vm.getId());
return UserVmJoinVOToVmConverter.toVm(vo, this::getHostById, this::listDiskAttachmentsByInstanceId,
this::listNicsByInstance, false);
return UserVmJoinVOToVmConverter.toVm(vo, this::getHostById, this::getDetailsByInstanceId,
this::listDiskAttachmentsByInstanceId, this::listNicsByInstance, false);
} catch (InsufficientCapacityException | ResourceUnavailableException | ResourceAllocationException | CloudRuntimeException e) {
throw new CloudRuntimeException("Failed to create VM: " + e.getMessage(), e);
}
@ -1266,6 +1266,10 @@ public class ServerAdapter extends ManagerBase {
return networkDao.findById(networkId);
}
protected Map<String, String> getDetailsByInstanceId(Long instanceId) {
return vmInstanceDetailsDao.listDetailsKeyPairs(instanceId, true);
}
public List<Job> listAllJobs() {
Pair<User, Account> serviceUserAccount = getServiceAccount();
List<Long> jobIds = asyncJobDao.listPendingJobIdsForAccount(serviceUserAccount.second().getId());

View File

@ -98,7 +98,7 @@ public class AsyncJobJoinVOToJobConverter {
public static VmAction toVmAction(final AsyncJobJoinVO vo, final UserVmJoinVO vm) {
VmAction action = new VmAction();
fillAction(action, vo);
action.setVm(UserVmJoinVOToVmConverter.toVm(vm, null, null, null, false));
action.setVm(UserVmJoinVOToVmConverter.toVm(vm, null, null, null, null, false));
return action;
}

View File

@ -20,9 +20,11 @@ package org.apache.cloudstack.veeam.api.converter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.veeam.VeeamControlService;
import org.apache.cloudstack.veeam.api.ApiService;
import org.apache.cloudstack.veeam.api.VmsRouteHandler;
@ -37,6 +39,7 @@ import org.apache.cloudstack.veeam.api.dto.OvfXmlUtil;
import org.apache.cloudstack.veeam.api.dto.Ref;
import org.apache.cloudstack.veeam.api.dto.Topology;
import org.apache.cloudstack.veeam.api.dto.Vm;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.api.query.vo.HostJoinVO;
@ -54,6 +57,7 @@ public final class UserVmJoinVOToVmConverter {
* @param src UserVmJoinVO
*/
public static Vm toVm(final UserVmJoinVO src, final Function<Long, HostJoinVO> hostResolver,
final Function<Long, Map<String, String>> detailsResolver,
final Function<Long, List<DiskAttachment>> disksResolver,
final Function<UserVmJoinVO, List<Nic>> nicsResolver,
final boolean allContent) {
@ -124,11 +128,11 @@ public final class UserVmJoinVOToVmConverter {
boot.setDevices(NamedList.of("device", List.of("hd")));
os.setBoot(boot);
dst.setOs(os);
Vm.Bios bios = new Vm.Bios();
bios.setType("q35_secure_boot");
Vm.Bios.BootMenu bootMenu = new Vm.Bios.BootMenu();
bootMenu.setEnabled("false");
bios.setBootMenu(bootMenu);
Vm.Bios bios = Vm.Bios.getDefault();
if (detailsResolver != null) {
Map<String, String> details = detailsResolver.apply(src.getId());
Vm.Bios.updateBios(bios, MapUtils.getString(details, ApiConstants.BootType.UEFI.toString()));
}
dst.setBios(bios);
dst.setType("desktop");
dst.setOrigin("ovirt");
@ -176,9 +180,10 @@ public final class UserVmJoinVOToVmConverter {
return initialization;
}
public static List<Vm> toVmList(final List<UserVmJoinVO> srcList, final Function<Long, HostJoinVO> hostResolver) {
public static List<Vm> toVmList(final List<UserVmJoinVO> srcList, final Function<Long, HostJoinVO> hostResolver,
final Function<Long, Map<String, String>> detailsResolver) {
return srcList.stream()
.map(v -> toVm(v, hostResolver, null, null, false))
.map(v -> toVm(v, hostResolver, detailsResolver, null, null, false))
.collect(Collectors.toList());
}

View File

@ -230,7 +230,7 @@ public class OvfXmlUtil {
sb.append("<ConsoleDisconnectAction>LOCK_SCREEN</ConsoleDisconnectAction>");
sb.append("<ConsoleDisconnectActionDelay>0</ConsoleDisconnectActionDelay>");
sb.append("<CustomEmulatedMachine></CustomEmulatedMachine>");
sb.append("<BiosType>").append(mapBiosType(vm.getBios() != null ? vm.getBios().getType() : null)).append("</BiosType>");
sb.append("<BiosType>").append(vm.getBios() != null ? vm.getBios().getTypeOrdinal() : 1).append("</BiosType>");
sb.append("<CustomCpuName></CustomCpuName>");
sb.append("<PredefinedProperties></PredefinedProperties>");
sb.append("<UserDefinedProperties></UserDefinedProperties>");
@ -456,6 +456,9 @@ public class OvfXmlUtil {
if (StringUtils.isNotBlank(templateId)) {
vm.setTemplate(Ref.of("", templateId));
}
String biosType = xpathString(xpath, contentNode, "./*[local-name()='BiosType']/text()");
Vm.Bios bios = Vm.Bios.getBiosFromOrdinal(biosType);
vm.setBios(bios);
}
private static void updateFromXmlHardwareSection(Vm vm, Node hwSection, XPath xpath) throws XPathExpressionException {
@ -646,17 +649,6 @@ public class OvfXmlUtil {
return "true".equalsIgnoreCase(sparse) ? "Sparse" : "Preallocated";
}
private static int mapBiosType(String biosType) {
if (StringUtils.isBlank(biosType)) {
return 2;
}
String t = biosType.toLowerCase(Locale.ROOT);
if (t.contains("uefi") || t.contains("secure")) {
return 2;
}
return 0;
}
private static String mapBalloonEnabled(Vm vm) {
if (vm.getMemoryPolicy() == null || vm.getMemoryPolicy().getBallooning() == null) {
return "true";

View File

@ -19,6 +19,10 @@ package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import org.apache.cloudstack.api.ApiConstants;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
@ -302,6 +306,18 @@ public final class Vm extends BaseDto {
return type;
}
@JsonIgnore
public int getTypeOrdinal() {
switch (type) {
case "q35_secure_boot":
return 4;
case "q35_ovmf":
return 2;
default:
return 1; // default to i440fx_sea_bios
}
}
public void setType(String type) {
this.type = type;
}
@ -327,6 +343,60 @@ public final class Vm extends BaseDto {
this.enabled = enabled;
}
}
public static Bios getDefault() {
Bios bios = new Bios();
bios.setType("i440fx_sea_bios");
BootMenu bootMenu = new BootMenu();
bootMenu.setEnabled("false");
bios.setBootMenu(bootMenu);
return bios;
}
public static void updateBios(Bios bios, String bootMode) {
if (StringUtils.isEmpty(bootMode)) {
return;
}
if (ApiConstants.BootMode.SECURE.toString().equals(bootMode)) {
bios.setType("q35_secure_boot");
return;
}
bios.setType("q35_ovmf");
}
public static Bios getBiosFromOrdinal(String bootTypeStr) {
Bios bios = getDefault();
if (StringUtils.isEmpty(bootTypeStr)) {
return bios;
}
int type = 1;
try {
type = Integer.parseInt(bootTypeStr);
} catch (NumberFormatException e) {
return bios;
}
if (type == 2 || type == 3) {
bios.setType("q35_ovmf");
} else if (type == 4) {
bios.setType("q35_secure_boot");
}
return bios;
}
public static Pair<ApiConstants.BootType, ApiConstants.BootMode> retrieveBootOptions(Bios bios) {
Pair<ApiConstants.BootType, ApiConstants.BootMode> defaultValue =
new Pair<>(ApiConstants.BootType.BIOS, ApiConstants.BootMode.LEGACY);
if (bios == null || StringUtils.isEmpty(bios.getType())) {
return defaultValue;
}
if ("q35_secure_boot".equals(bios.getType())) {
return new Pair<>(ApiConstants.BootType.UEFI, ApiConstants.BootMode.SECURE);
}
if (bios.getType().startsWith("q35_")) {
return new Pair<>(ApiConstants.BootType.UEFI, ApiConstants.BootMode.LEGACY);
}
return defaultValue;
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)