From e7172161dd2aab58a1dee8db5dbd0f7181afe1ac Mon Sep 17 00:00:00 2001 From: Abhisar Sinha <63767682+abh1sar@users.noreply.github.com> Date: Tue, 22 Jul 2025 18:42:24 +0530 Subject: [PATCH] Guard OS type update for iso/template with existing vms (#11215) * Guard OS type update for iso/template with existing vms * fix identation * rename vm -> instance * force update iso/template as true by default via api * add missing message.success.update.iso label --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../api/BaseUpdateTemplateOrIsoCmd.java | 8 ++++++++ .../cloud/template/TemplateManagerImpl.java | 6 ++++++ ui/public/locales/en.json | 2 ++ ui/src/views/image/UpdateISO.vue | 20 +++++++++++++++++-- ui/src/views/image/UpdateTemplate.vue | 19 +++++++++++++++++- 6 files changed, 53 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index f5a1636c30e..607504835c0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -223,6 +223,7 @@ public class ApiConstants { public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage"; public static final String FORCE_DELETE_HOST = "forcedeletehost"; public static final String FORCE_MS_TO_IMPORT_VM_FILES = "forcemstoimportvmfiles"; + public static final String FORCE_UPDATE_OS_TYPE = "forceupdateostype"; public static final String FORMAT = "format"; public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork"; public static final String FOR_SYSTEM_VMS = "forsystemvms"; diff --git a/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java index 9a8282df112..8489bf05ec7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java @@ -51,6 +51,10 @@ public abstract class BaseUpdateTemplateOrIsoCmd extends BaseCmd { description = "the ID of the OS type that best represents the OS of this image.") private Long osTypeId; + @Parameter(name = ApiConstants.FORCE_UPDATE_OS_TYPE, type = CommandType.BOOLEAN, since = "4.21", description = "Force OS type update. Warning: Updating OS type will " + + "update the guest OS configuration for all the existing Instances deployed with this template/iso, which may affect their behavior.") + private Boolean forceUpdateOsType; + @Parameter(name = ApiConstants.FORMAT, type = CommandType.STRING, description = "the format for the image") private String format; @@ -112,6 +116,10 @@ public abstract class BaseUpdateTemplateOrIsoCmd extends BaseCmd { return osTypeId; } + public Boolean getForceUpdateOsType() { + return forceUpdateOsType; + } + public Boolean getPasswordEnabled() { return passwordEnabled; } diff --git a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java index 6759144837d..d8e90cd3d05 100755 --- a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java @@ -2238,6 +2238,12 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, sc.addAnd("state", SearchCriteria.Op.NEQ, State.Expunging); List vms = _vmInstanceDao.search(sc, null); if (vms != null && !vms.isEmpty()) { + if (Boolean.FALSE.equals(cmd.getForceUpdateOsType())) { + String message = String.format("Updating OS type will update the guest OS configuration " + + "for all of the %d Instance(s) deployed with this Template/ISO, which may affect their behavior. " + + "To proceed, please set the 'forceupdateostype' parameter to true.", vms.size()); + throw new InvalidParameterValueException(message); + } for (VMInstanceVO vm: vms) { vm.setGuestOSId(guestOSId); _vmInstanceDao.update(vm.getId(), vm); diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 3fdfa03ecd0..93485043010 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1039,6 +1039,7 @@ "label.forbidden": "Forbidden", "label.forced": "Force", "label.force.ms.to.import.vm.files": "Enable to force OVF Download via Management Server. Disable to use KVM Host ovftool (if installed)", +"label.force.update.os.type": "Force update OS type", "label.force.stop": "Force stop", "label.force.reboot": "Force reboot", "label.forceencap": "Force UDP encapsulation of ESP packets", @@ -3693,6 +3694,7 @@ "message.success.update.ipaddress": "Successfully updated IP address", "message.success.update.iprange": "Successfully updated IP range", "message.success.update.ipv4.subnet": "Successfully updated IPv4 subnet", +"message.success.update.iso": "Successfully updated ISO", "message.success.update.kubeversion": "Successfully updated Kubernetes supported version", "message.success.update.network": "Successfully updated Network", "message.success.update.template": "Successfully updated Template", diff --git a/ui/src/views/image/UpdateISO.vue b/ui/src/views/image/UpdateISO.vue index 856038f2d5f..f4b46665352 100644 --- a/ui/src/views/image/UpdateISO.vue +++ b/ui/src/views/image/UpdateISO.vue @@ -67,6 +67,13 @@ + + + + +