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