This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.20 by this push:
     new a0f35a186d8 Fixes issue with loading Capacity dashboard when mulitple 
backup providers configured (#12550)
a0f35a186d8 is described below

commit a0f35a186d826a7acbd65041bba1c4d2db1ddbfc
Author: Pearl Dsilva <[email protected]>
AuthorDate: Mon Feb 9 06:12:28 2026 -0500

    Fixes issue with loading Capacity dashboard when mulitple backup providers 
configured (#12550)
---
 .../apache/cloudstack/backup/BackupManager.java    | 16 +++++++--
 .../framework/config/ValidatedConfigKey.java       | 38 ++++++++++++++++++++++
 .../configuration/ConfigurationManagerImpl.java    |  7 ++++
 .../cloudstack/backup/BackupManagerImpl.java       |  8 ++---
 4 files changed, 63 insertions(+), 6 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 78d189c3bf1..0090b4f6b16 100644
--- a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java
+++ b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java
@@ -26,6 +26,7 @@ import 
org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
 import org.apache.cloudstack.api.command.user.backup.ListBackupOfferingsCmd;
 import org.apache.cloudstack.api.command.user.backup.ListBackupsCmd;
 import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.ValidatedConfigKey;
 import org.apache.cloudstack.framework.config.Configurable;
 
 import com.cloud.utils.Pair;
@@ -42,10 +43,11 @@ public interface BackupManager extends BackupService, 
Configurable, PluggableSer
             "false",
             "Is backup and recovery framework enabled.", false, 
ConfigKey.Scope.Zone);
 
-    ConfigKey<String> BackupProviderPlugin = new ConfigKey<>("Advanced", 
String.class,
+    ConfigKey<String> BackupProviderPlugin = new 
ValidatedConfigKey<>("Advanced", String.class,
             "backup.framework.provider.plugin",
             "dummy",
-            "The backup and recovery provider plugin.", true, 
ConfigKey.Scope.Zone, BackupFrameworkEnabled.key());
+            "The backup and recovery provider plugin. Valid plugin values: 
dummy, veeam, networker and nas",
+            true, ConfigKey.Scope.Zone, BackupFrameworkEnabled.key(), value -> 
validateBackupProviderConfig((String)value));
 
     ConfigKey<Long> BackupSyncPollingInterval = new ConfigKey<>("Advanced", 
Long.class,
             "backup.framework.sync.interval",
@@ -148,4 +150,14 @@ public interface BackupManager extends BackupService, 
Configurable, PluggableSer
     boolean deleteBackup(final Long backupId, final Boolean forced);
 
     BackupOffering updateBackupOffering(UpdateBackupOfferingCmd 
updateBackupOfferingCmd);
+
+    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<String> 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));
+        }
+    }
 }
diff --git 
a/framework/config/src/main/java/org/apache/cloudstack/framework/config/ValidatedConfigKey.java
 
b/framework/config/src/main/java/org/apache/cloudstack/framework/config/ValidatedConfigKey.java
new file mode 100644
index 00000000000..4fcbe4151d3
--- /dev/null
+++ 
b/framework/config/src/main/java/org/apache/cloudstack/framework/config/ValidatedConfigKey.java
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.framework.config;
+
+import java.util.function.Consumer;
+
+public class ValidatedConfigKey<T> extends ConfigKey<T> {
+    private final Consumer<T> validator;
+
+    public ValidatedConfigKey(String category, Class<T> type, String name, 
String defaultValue, String description, boolean dynamic, Scope scope, String 
parent, Consumer<T> validator) {
+        super(category, type, name, defaultValue, description, dynamic, scope, 
parent);
+        this.validator = validator;
+    }
+
+    public Consumer<T> getValidator() {
+        return validator;
+    }
+
+    public void validateValue(String value) {
+        if (validator != null) {
+            validator.accept((T) value);
+        }
+    }
+}
diff --git 
a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java 
b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
index 3a4bdf8afec..eb138bb10b0 100644
--- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -107,6 +107,7 @@ import 
org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
 import org.apache.cloudstack.framework.config.ConfigDepot;
 import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.cloudstack.framework.config.ValidatedConfigKey;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
 import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
@@ -716,6 +717,12 @@ public class ConfigurationManagerImpl extends ManagerBase 
implements Configurati
             throw new InvalidParameterValueException(validationMsg);
         }
 
+        ConfigKey<?> configKey = _configDepot.get(name);
+        if (configKey instanceof ValidatedConfigKey) {
+            ValidatedConfigKey<?> validatedConfigKey = (ValidatedConfigKey<?>) 
configKey;
+            validatedConfigKey.validateValue(value);
+        }
+
         // If scope of the parameter is given then it needs to be updated in 
the
         // corresponding details table,
         // if scope is mentioned as global or not mentioned then it is normal
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 dc2677a507f..2e49f4b7ad0 100644
--- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
@@ -972,10 +972,10 @@ public class BackupManagerImpl extends ManagerBase 
implements BackupManager {
         if (StringUtils.isEmpty(name)) {
             throw new CloudRuntimeException("Invalid backup provider name 
provided");
         }
-        if (!backupProvidersMap.containsKey(name)) {
-            throw new CloudRuntimeException("Failed to find backup provider by 
the name: " + name);
-        }
-        return backupProvidersMap.get(name);
+       if (!backupProvidersMap.containsKey(name)) {
+           throw new CloudRuntimeException("Failed to find backup provider by 
the name: " + name);
+       }
+       return backupProvidersMap.get(name);
     }
 
     @Override

Reply via email to