From 90d87d0e9234528c70b9c9b305b5fb822f073a32 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 18 Mar 2026 14:24:57 +0530 Subject: [PATCH] restore with correct bios type Signed-off-by: Abhishek Kumar --- .../veeam/adapter/ServerAdapter.java | 24 ++++--- .../AsyncJobJoinVOToJobConverter.java | 2 +- .../converter/UserVmJoinVOToVmConverter.java | 19 +++-- .../cloudstack/veeam/api/dto/OvfXmlUtil.java | 16 ++--- .../apache/cloudstack/veeam/api/dto/Vm.java | 70 +++++++++++++++++++ 5 files changed, 101 insertions(+), 30 deletions(-) diff --git a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/adapter/ServerAdapter.java b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/adapter/ServerAdapter.java index 9a7ee9ceca7..6e252829bad 100644 --- a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/adapter/ServerAdapter.java +++ b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/adapter/ServerAdapter.java @@ -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 listAllInstances() { List 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 bootOptions = Vm.Bios.retrieveBootOptions(request.getBios()); Ternary 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 getDetailsByInstanceId(Long instanceId) { + return vmInstanceDetailsDao.listDetailsKeyPairs(instanceId, true); + } + public List listAllJobs() { Pair serviceUserAccount = getServiceAccount(); List jobIds = asyncJobDao.listPendingJobIdsForAccount(serviceUserAccount.second().getId()); diff --git a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/AsyncJobJoinVOToJobConverter.java b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/AsyncJobJoinVOToJobConverter.java index 625c9d9e469..dc2853dfd76 100644 --- a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/AsyncJobJoinVOToJobConverter.java +++ b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/AsyncJobJoinVOToJobConverter.java @@ -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; } diff --git a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/UserVmJoinVOToVmConverter.java b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/UserVmJoinVOToVmConverter.java index 42431dc357b..44691a0ef49 100644 --- a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/UserVmJoinVOToVmConverter.java +++ b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/UserVmJoinVOToVmConverter.java @@ -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 hostResolver, + final Function> detailsResolver, final Function> disksResolver, final Function> 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 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 toVmList(final List srcList, final Function hostResolver) { + public static List toVmList(final List srcList, final Function hostResolver, + final Function> detailsResolver) { return srcList.stream() - .map(v -> toVm(v, hostResolver, null, null, false)) + .map(v -> toVm(v, hostResolver, detailsResolver, null, null, false)) .collect(Collectors.toList()); } diff --git a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/OvfXmlUtil.java b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/OvfXmlUtil.java index 8ca75a27485..fcccf299f27 100644 --- a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/OvfXmlUtil.java +++ b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/OvfXmlUtil.java @@ -230,7 +230,7 @@ public class OvfXmlUtil { sb.append("LOCK_SCREEN"); sb.append("0"); sb.append(""); - sb.append("").append(mapBiosType(vm.getBios() != null ? vm.getBios().getType() : null)).append(""); + sb.append("").append(vm.getBios() != null ? vm.getBios().getTypeOrdinal() : 1).append(""); sb.append(""); sb.append(""); sb.append(""); @@ -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"; diff --git a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Vm.java b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Vm.java index 700124899dd..c6ade15853e 100644 --- a/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Vm.java +++ b/plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/dto/Vm.java @@ -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 retrieveBootOptions(Bios bios) { + Pair 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)