From 5ad3651f272dcc5e959b757ad81a4948993518f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yi=C4=9Fit=20Can=20Ba=C5=9Falma?= Date: Thu, 4 Jun 2026 00:00:03 +0300 Subject: [PATCH 1/4] Fix --- .../cloudstack/backup/BackupManager.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java index 07c32a7f8a5d..9b0503dc2ab1 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Map; +import java.util.Arrays; import com.cloud.capacity.Capacity; import com.cloud.exception.ResourceAllocationException; @@ -57,9 +58,16 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer ConfigKey BackupProviderPlugin = new ValidatedConfigKey<>("Advanced", String.class, "backup.framework.provider.plugin", "dummy", - "The backup and recovery provider plugin. Valid plugin values: dummy, veeam, networker and nas", + "The backup and recovery provider plugin. Default built-in plugins: dummy, veeam, networker, nas. Additional plugins can be allowed via backup.framework.provider.plugin.allowed setting.", true, ConfigKey.Scope.Zone, BackupFrameworkEnabled.key(), value -> validateBackupProviderConfig((String)value)); + ConfigKey AllowedBackupProviderPlugins = new ConfigKey<>( + "Advanced", String.class, + "backup.framework.provider.plugin.allowed", + "dummy,veeam,networker,nas", + "Comma-separated list of allowed backup provider plugins.", + true, ConfigKey.Scope.Zone); + ConfigKey BackupSyncPollingInterval = new ConfigKey<>("Advanced", Long.class, "backup.framework.sync.interval", "300", @@ -254,9 +262,14 @@ static void validateBackupProviderConfig(String value) { if (value != null && (value.contains(",") || value.trim().contains(" "))) { throw new IllegalArgumentException("Multiple backup provider plugins are not supported. Please provide a single plugin value."); } - List validPlugins = List.of("dummy", "veeam", "networker", "nas"); - if (value != null && !validPlugins.contains(value)) { - throw new IllegalArgumentException("Invalid backup provider plugin: " + value + ". Valid plugin values are: " + String.join(", ", validPlugins)); + String allowed = AllowedBackupProviderPlugins.value(); + if (allowed != null && value != null) { + List validPlugins = Arrays.asList(allowed.split(",")); + if (!validPlugins.contains(value.trim())) { + throw new IllegalArgumentException("Invalid backup provider plugin: " + value + + ". Valid plugin values are: " + allowed + + ". You can add more plugins via backup.framework.provider.plugin.allowed setting."); + } } } } From 6b1bb4843d68dddff6ae0557999e13d6916770a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yi=C4=9Fit=20Can=20Ba=C5=9Falma?= Date: Sat, 20 Jun 2026 10:01:15 +0300 Subject: [PATCH 2/4] fix: validate backup provider plugin via Spring bean instead of allowed list --- .../cloudstack/backup/BackupManager.java | 29 ++----------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java index 9b0503dc2ab1..281e4185ca2b 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java @@ -19,7 +19,6 @@ import java.util.List; import java.util.Map; -import java.util.Arrays; import com.cloud.capacity.Capacity; import com.cloud.exception.ResourceAllocationException; @@ -55,18 +54,11 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer "false", "Is backup and recovery framework enabled.", false, ConfigKey.Scope.Zone); - ConfigKey BackupProviderPlugin = new ValidatedConfigKey<>("Advanced", String.class, + ConfigKey BackupProviderPlugin = new ConfigKey<>("Advanced", String.class, "backup.framework.provider.plugin", "dummy", - "The backup and recovery provider plugin. Default built-in plugins: dummy, veeam, networker, nas. Additional plugins can be allowed via backup.framework.provider.plugin.allowed setting.", - true, ConfigKey.Scope.Zone, BackupFrameworkEnabled.key(), value -> validateBackupProviderConfig((String)value)); - - ConfigKey AllowedBackupProviderPlugins = new ConfigKey<>( - "Advanced", String.class, - "backup.framework.provider.plugin.allowed", - "dummy,veeam,networker,nas", - "Comma-separated list of allowed backup provider plugins.", - true, ConfigKey.Scope.Zone); + "The backup and recovery provider plugin.", + true, ConfigKey.Scope.Zone, BackupFrameworkEnabled.key()); ConfigKey BackupSyncPollingInterval = new ConfigKey<>("Advanced", Long.class, "backup.framework.sync.interval", @@ -257,19 +249,4 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer Capacity getBackupStorageUsedStats(Long zoneId); void checkAndRemoveBackupOfferingBeforeExpunge(VirtualMachine vm); - - static void validateBackupProviderConfig(String value) { - if (value != null && (value.contains(",") || value.trim().contains(" "))) { - throw new IllegalArgumentException("Multiple backup provider plugins are not supported. Please provide a single plugin value."); - } - String allowed = AllowedBackupProviderPlugins.value(); - if (allowed != null && value != null) { - List validPlugins = Arrays.asList(allowed.split(",")); - if (!validPlugins.contains(value.trim())) { - throw new IllegalArgumentException("Invalid backup provider plugin: " + value + - ". Valid plugin values are: " + allowed + - ". You can add more plugins via backup.framework.provider.plugin.allowed setting."); - } - } - } } From 38457bc944e726378374f699dfbf7d5886aceae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yi=C4=9Fit=20Can=20Ba=C5=9Falma?= Date: Sun, 21 Jun 2026 18:11:35 +0300 Subject: [PATCH 3/4] fix: unused import error --- .../main/java/org/apache/cloudstack/backup/BackupManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java index 281e4185ca2b..69ccf3e91511 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java @@ -32,7 +32,6 @@ import org.apache.cloudstack.api.command.user.backup.ListBackupsCmd; import org.apache.cloudstack.api.response.BackupResponse; import org.apache.cloudstack.framework.config.ConfigKey; -import org.apache.cloudstack.framework.config.ValidatedConfigKey; import org.apache.cloudstack.framework.config.Configurable; import com.cloud.exception.ResourceUnavailableException; From de543b7c54e7023bb719e198b5b27477bf493aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yi=C4=9Fit=20Can=20Ba=C5=9Falma?= Date: Wed, 1 Jul 2026 21:50:08 +0300 Subject: [PATCH 4/4] fix: handle missing backup provider gracefully to prevent dashboard failure --- .../org/apache/cloudstack/backup/BackupManagerImpl.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java index ec87980e03a4..a33f1133fa64 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -1678,11 +1678,8 @@ public BackupProvider getBackupProvider(final Long zoneId) { public BackupProvider getBackupProvider(final String name) { if (StringUtils.isEmpty(name)) { - throw new CloudRuntimeException("Invalid backup provider name provided"); + return null; } - if (!backupProvidersMap.containsKey(name)) { - throw new CloudRuntimeException("Failed to find backup provider by the name: " + name); - } return backupProvidersMap.get(name); } @@ -2288,6 +2285,10 @@ public CapacityVO getBackupStorageUsedStats(Long zoneId) { return new CapacityVO(null, zoneId, null, null, 0L, 0L, Capacity.CAPACITY_TYPE_BACKUP_STORAGE); } final BackupProvider backupProvider = getBackupProvider(zoneId); + if (backupProvider == null) { + logger.warn("Backup provider not configured or not found for zone {}", zoneId); + return new CapacityVO(null, zoneId, null, null, 0L, 0L, Capacity.CAPACITY_TYPE_BACKUP_STORAGE); + } Pair backupUsage = backupProvider.getBackupStorageStats(zoneId); return new CapacityVO(null, zoneId, null, null, backupUsage.first(), backupUsage.second(), Capacity.CAPACITY_TYPE_BACKUP_STORAGE); }