mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Improve global settings UI to be more intuitive/logical (#5797)
Co-authored-by: Suresh Kumar Anaparti <suresh.anaparti@shapeblue.com> Co-authored-by: nvazquez <nicovazquez90@gmail.com> Co-authored-by: davidjumani <dj.davidjumani1994@gmail.com> Co-authored-by: dahn <daan.hoogland@gmail.com> Co-authored-by: dahn <daan@onecht.net>
This commit is contained in:
parent
3b6ce97097
commit
d8c7e34b38
@ -22,6 +22,7 @@ import java.util.Map;
|
||||
|
||||
import com.cloud.user.UserData;
|
||||
import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
|
||||
import org.apache.cloudstack.api.command.admin.config.ListCfgGroupsByCmd;
|
||||
import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
|
||||
import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd;
|
||||
import org.apache.cloudstack.api.command.admin.guest.AddGuestOsCmd;
|
||||
@ -63,6 +64,7 @@ import org.apache.cloudstack.api.command.user.userdata.RegisterUserDataCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.GetVMPasswordCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
|
||||
import org.apache.cloudstack.config.Configuration;
|
||||
import org.apache.cloudstack.config.ConfigurationGroup;
|
||||
|
||||
import com.cloud.alert.Alert;
|
||||
import com.cloud.capacity.Capacity;
|
||||
@ -102,6 +104,13 @@ public interface ManagementService {
|
||||
*/
|
||||
Pair<List<? extends Configuration>, Integer> searchForConfigurations(ListCfgsByCmd c);
|
||||
|
||||
/**
|
||||
* returns the the configuration groups
|
||||
*
|
||||
* @return list of configuration groups
|
||||
*/
|
||||
Pair<List<? extends ConfigurationGroup>, Integer> listConfigurationGroups(ListCfgGroupsByCmd cmd);
|
||||
|
||||
/**
|
||||
* Searches for Clusters by the specified search criteria
|
||||
*
|
||||
|
||||
@ -118,6 +118,7 @@ public class ApiConstants {
|
||||
public static final String MAX_IOPS = "maxiops";
|
||||
public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve";
|
||||
public static final String DATADISK_OFFERING_LIST = "datadiskofferinglist";
|
||||
public static final String DEFAULT_VALUE = "defaultvalue";
|
||||
public static final String DESCRIPTION = "description";
|
||||
public static final String DESTINATION = "destination";
|
||||
public static final String DESTINATION_ZONE_ID = "destzoneid";
|
||||
@ -187,6 +188,7 @@ public class ApiConstants {
|
||||
public static final String GATEWAY = "gateway";
|
||||
public static final String IP6_GATEWAY = "ip6gateway";
|
||||
public static final String GROUP = "group";
|
||||
public static final String SUBGROUP = "subgroup";
|
||||
public static final String GROUP_ID = "groupid";
|
||||
public static final String GSLB_LB_METHOD = "gslblbmethod";
|
||||
public static final String GSLB_SERVICE_DOMAIN_NAME = "gslbdomainname";
|
||||
@ -301,6 +303,7 @@ public class ApiConstants {
|
||||
public static final String IS_DEFAULT_USE = "defaultuse";
|
||||
public static final String OLD_FORMAT = "oldformat";
|
||||
public static final String OP = "op";
|
||||
public static final String OPTIONS = "options";
|
||||
public static final String OS_CATEGORY_ID = "oscategoryid";
|
||||
public static final String OS_CATEGORY_NAME = "oscategoryname";
|
||||
public static final String OS_ID = "osid";
|
||||
@ -312,6 +315,7 @@ public class ApiConstants {
|
||||
public static final String OUTPUT = "output";
|
||||
public static final String PROPERTIES = "properties";
|
||||
public static final String PARAMS = "params";
|
||||
public static final String PARENT = "parent";
|
||||
public static final String PARENT_ID = "parentid";
|
||||
public static final String PARENT_DOMAIN_ID = "parentdomainid";
|
||||
public static final String PARENT_TEMPLATE_ID = "parenttemplateid";
|
||||
@ -333,6 +337,7 @@ public class ApiConstants {
|
||||
public static final String POSITION = "position";
|
||||
public static final String POST_URL = "postURL";
|
||||
public static final String POWER_STATE = "powerstate";
|
||||
public static final String PRECEDENCE = "precedence";
|
||||
public static final String PRIVATE_INTERFACE = "privateinterface";
|
||||
public static final String PRIVATE_IP = "privateip";
|
||||
public static final String PRIVATE_PORT = "privateport";
|
||||
|
||||
@ -40,6 +40,7 @@ import org.apache.cloudstack.api.response.BackupScheduleResponse;
|
||||
import org.apache.cloudstack.api.response.CapacityResponse;
|
||||
import org.apache.cloudstack.api.response.ClusterResponse;
|
||||
import org.apache.cloudstack.api.response.ConditionResponse;
|
||||
import org.apache.cloudstack.api.response.ConfigurationGroupResponse;
|
||||
import org.apache.cloudstack.api.response.ConfigurationResponse;
|
||||
import org.apache.cloudstack.api.response.CounterResponse;
|
||||
import org.apache.cloudstack.api.response.CreateCmdResponse;
|
||||
@ -133,6 +134,7 @@ import org.apache.cloudstack.backup.Backup;
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
import org.apache.cloudstack.backup.BackupSchedule;
|
||||
import org.apache.cloudstack.config.Configuration;
|
||||
import org.apache.cloudstack.config.ConfigurationGroup;
|
||||
import org.apache.cloudstack.direct.download.DirectDownloadCertificate;
|
||||
import org.apache.cloudstack.direct.download.DirectDownloadCertificateHostMap;
|
||||
import org.apache.cloudstack.direct.download.DirectDownloadManager;
|
||||
@ -244,6 +246,8 @@ public interface ResponseGenerator {
|
||||
|
||||
ConfigurationResponse createConfigurationResponse(Configuration cfg);
|
||||
|
||||
ConfigurationGroupResponse createConfigurationGroupResponse(ConfigurationGroup cfgGroup);
|
||||
|
||||
SnapshotResponse createSnapshotResponse(Snapshot snapshot);
|
||||
|
||||
SnapshotPolicyResponse createSnapshotPolicyResponse(SnapshotPolicy policy);
|
||||
|
||||
@ -0,0 +1,79 @@
|
||||
// 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.api.command.admin.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.ConfigurationGroupResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.config.ConfigurationGroup;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
@APICommand(name = ListCfgGroupsByCmd.APINAME, description = "Lists all configuration groups (primarily used for UI).", responseObject = ConfigurationGroupResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.18.0")
|
||||
public class ListCfgGroupsByCmd extends BaseListCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(ListCfgGroupsByCmd.class.getName());
|
||||
|
||||
public static final String APINAME = "listConfigurationGroups";
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// ////////////// API parameters /////////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name = ApiConstants.GROUP, type = CommandType.STRING, description = "lists configuration group by group name")
|
||||
private String groupName;
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// ///////////////// Accessors ///////////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// ///////////// API Implementation///////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Pair<List<? extends ConfigurationGroup>, Integer> result = _mgr.listConfigurationGroups(this);
|
||||
ListResponse<ConfigurationGroupResponse> response = new ListResponse<>();
|
||||
List<ConfigurationGroupResponse> configGroupResponses = new ArrayList<>();
|
||||
for (ConfigurationGroup cfgGroup : result.first()) {
|
||||
ConfigurationGroupResponse cfgGroupResponse = _responseGenerator.createConfigurationGroupResponse(cfgGroup);
|
||||
configGroupResponses.add(cfgGroupResponse);
|
||||
}
|
||||
|
||||
response.setResponses(configGroupResponses, result.second());
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
}
|
||||
@ -19,7 +19,10 @@ package org.apache.cloudstack.api.command.admin.config;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
@ -35,7 +38,9 @@ import org.apache.cloudstack.api.response.StoragePoolResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
import org.apache.cloudstack.config.Configuration;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@APICommand(name = "listConfigurations", description = "Lists all configurations.", responseObject = ConfigurationResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
@ -89,6 +94,15 @@ public class ListCfgsByCmd extends BaseListCmd {
|
||||
description = "the ID of the Image Store to update the parameter value for corresponding image store")
|
||||
private Long imageStoreId;
|
||||
|
||||
@Parameter(name = ApiConstants.GROUP, type = CommandType.STRING, description = "lists configuration by group name (primarily used for UI)", since = "4.18.0")
|
||||
private String groupName;
|
||||
|
||||
@Parameter(name = ApiConstants.SUBGROUP, type = CommandType.STRING, description = "lists configuration by subgroup name (primarily used for UI)", since = "4.18.0")
|
||||
private String subGroupName;
|
||||
|
||||
@Parameter(name = ApiConstants.PARENT, type = CommandType.STRING, description = "lists configuration by parent name (primarily used for UI)", since = "4.18.0")
|
||||
private String parentName;
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// ///////////////// Accessors ///////////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
@ -125,6 +139,26 @@ public class ListCfgsByCmd extends BaseListCmd {
|
||||
return imageStoreId;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public String getSubGroupName() {
|
||||
return subGroupName;
|
||||
}
|
||||
|
||||
public String getParentName() {
|
||||
return parentName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPageSize() {
|
||||
if (StringUtils.isNotEmpty(getGroupName())) {
|
||||
return Integer.valueOf(s_pageSizeUnlimited.intValue());
|
||||
}
|
||||
return super.getPageSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getPageSizeVal() {
|
||||
Long defaultPageSize = 500L;
|
||||
@ -143,37 +177,74 @@ public class ListCfgsByCmd extends BaseListCmd {
|
||||
// ///////////// API Implementation///////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
|
||||
private void setScope(ConfigurationResponse cfgResponse) {
|
||||
if (!matchesConfigurationGroup(cfgResponse)) {
|
||||
return;
|
||||
}
|
||||
cfgResponse.setObjectName("configuration");
|
||||
if (getZoneId() != null) {
|
||||
cfgResponse.setScope("zone");
|
||||
}
|
||||
if (getClusterId() != null) {
|
||||
cfgResponse.setScope("cluster");
|
||||
}
|
||||
if (getStoragepoolId() != null) {
|
||||
cfgResponse.setScope("storagepool");
|
||||
}
|
||||
if (getAccountId() != null) {
|
||||
cfgResponse.setScope("account");
|
||||
}
|
||||
if (getDomainId() != null) {
|
||||
cfgResponse.setScope("domain");
|
||||
}
|
||||
if (getImageStoreId() != null){
|
||||
cfgResponse.setScope("imagestore");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Pair<List<? extends Configuration>, Integer> result = _mgr.searchForConfigurations(this);
|
||||
ListResponse<ConfigurationResponse> response = new ListResponse<ConfigurationResponse>();
|
||||
List<ConfigurationResponse> configResponses = new ArrayList<ConfigurationResponse>();
|
||||
for (Configuration cfg : result.first()) {
|
||||
ConfigurationResponse cfgResponse = _responseGenerator.createConfigurationResponse(cfg);
|
||||
cfgResponse.setObjectName("configuration");
|
||||
if (getZoneId() != null) {
|
||||
cfgResponse.setScope("zone");
|
||||
validateParameters();
|
||||
try {
|
||||
Pair<List<? extends Configuration>, Integer> result = _mgr.searchForConfigurations(this);
|
||||
ListResponse<ConfigurationResponse> response = new ListResponse<>();
|
||||
List<ConfigurationResponse> configResponses = new ArrayList<>();
|
||||
for (Configuration cfg : result.first()) {
|
||||
ConfigurationResponse cfgResponse = _responseGenerator.createConfigurationResponse(cfg);
|
||||
setScope(cfgResponse);
|
||||
configResponses.add(cfgResponse);
|
||||
}
|
||||
if (getClusterId() != null) {
|
||||
cfgResponse.setScope("cluster");
|
||||
}
|
||||
if (getStoragepoolId() != null) {
|
||||
cfgResponse.setScope("storagepool");
|
||||
}
|
||||
if (getAccountId() != null) {
|
||||
cfgResponse.setScope("account");
|
||||
}
|
||||
if (getDomainId() != null) {
|
||||
cfgResponse.setScope("domain");
|
||||
}
|
||||
if (getImageStoreId() != null){
|
||||
cfgResponse.setScope("imagestore");
|
||||
}
|
||||
configResponses.add(cfgResponse);
|
||||
}
|
||||
|
||||
response.setResponses(configResponses, result.second());
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
if (StringUtils.isNotEmpty(getGroupName())) {
|
||||
response.setResponses(configResponses, configResponses.size());
|
||||
} else {
|
||||
response.setResponses(configResponses, result.second());
|
||||
}
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} catch (InvalidParameterValueException e) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, e.getMessage());
|
||||
} catch (CloudRuntimeException e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void validateParameters() {
|
||||
if (StringUtils.isNotEmpty(getSubGroupName()) && StringUtils.isEmpty(getGroupName())) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Configuration group name must be specified with the subgroup name");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchesConfigurationGroup(ConfigurationResponse cfgResponse) {
|
||||
if (StringUtils.isNotEmpty(getGroupName())) {
|
||||
if (!(getGroupName().equalsIgnoreCase(cfgResponse.getGroup()))) {
|
||||
return false;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(getSubGroupName()) &&
|
||||
!getSubGroupName().equalsIgnoreCase(cfgResponse.getSubGroup())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
// 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.api.response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
public class ConfigurationGroupResponse extends BaseResponse {
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "the name of the configuration group")
|
||||
private String groupName;
|
||||
|
||||
@SerializedName(ApiConstants.SUBGROUP)
|
||||
@Param(description = "the subgroups of the configuration group", responseObject = ConfigurationSubGroupResponse.class)
|
||||
private List<ConfigurationSubGroupResponse> subGroups;
|
||||
|
||||
@SerializedName(ApiConstants.DESCRIPTION)
|
||||
@Param(description = "the description of the configuration group")
|
||||
private String description;
|
||||
|
||||
@SerializedName(ApiConstants.PRECEDENCE)
|
||||
@Param(description = "the precedence of the configuration group")
|
||||
private Long precedence;
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public void setGroupName(String groupName) {
|
||||
this.groupName = groupName;
|
||||
}
|
||||
|
||||
public List<ConfigurationSubGroupResponse> getSubGroups() {
|
||||
return subGroups;
|
||||
}
|
||||
|
||||
public void setSubGroups(List<ConfigurationSubGroupResponse> subGroups) {
|
||||
this.subGroups = subGroups;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Long getPrecedence() {
|
||||
return precedence;
|
||||
}
|
||||
|
||||
public void setPrecedence(Long precedence) {
|
||||
this.precedence = precedence;
|
||||
}
|
||||
}
|
||||
@ -28,6 +28,14 @@ public class ConfigurationResponse extends BaseResponse {
|
||||
@Param(description = "the category of the configuration")
|
||||
private String category;
|
||||
|
||||
@SerializedName(ApiConstants.GROUP)
|
||||
@Param(description = "the group of the configuration", since = "4.18.0")
|
||||
private String group;
|
||||
|
||||
@SerializedName(ApiConstants.SUBGROUP)
|
||||
@Param(description = "the subgroup of the configuration", since = "4.18.0")
|
||||
private String subGroup;
|
||||
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "the name of the configuration")
|
||||
private String name;
|
||||
@ -36,6 +44,10 @@ public class ConfigurationResponse extends BaseResponse {
|
||||
@Param(description = "the value of the configuration")
|
||||
private String value;
|
||||
|
||||
@SerializedName(ApiConstants.DEFAULT_VALUE)
|
||||
@Param(description = "the default value of the configuration", since = "4.18.0")
|
||||
private String defaultValue;
|
||||
|
||||
@SerializedName(ApiConstants.SCOPE)
|
||||
@Param(description = "scope(zone/cluster/pool/account) of the parameter that needs to be updated")
|
||||
private String scope;
|
||||
@ -52,6 +64,26 @@ public class ConfigurationResponse extends BaseResponse {
|
||||
@Param(description = "true if the configuration is dynamic")
|
||||
private boolean isDynamic;
|
||||
|
||||
@SerializedName(ApiConstants.COMPONENT)
|
||||
@Param(description = "the component of the configuration", since = "4.18.0")
|
||||
private String component;
|
||||
|
||||
@SerializedName(ApiConstants.PARENT)
|
||||
@Param(description = "the name of the parent configuration", since = "4.18.0")
|
||||
private String parent;
|
||||
|
||||
@SerializedName(ApiConstants.DISPLAY_TEXT)
|
||||
@Param(description = "the display text of the configuration", since = "4.18.0")
|
||||
private String displayText;
|
||||
|
||||
@SerializedName(ApiConstants.TYPE)
|
||||
@Param(description = "the type of the configuration value", since = "4.18.0")
|
||||
private String type;
|
||||
|
||||
@SerializedName(ApiConstants.OPTIONS)
|
||||
@Param(description = "the possible options of the configuration value", since = "4.18.0")
|
||||
private String options;
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
@ -60,6 +92,22 @@ public class ConfigurationResponse extends BaseResponse {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public String getSubGroup() {
|
||||
return subGroup;
|
||||
}
|
||||
|
||||
public void setSubGroup(String subGroup) {
|
||||
this.subGroup = subGroup;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@ -76,6 +124,14 @@ public class ConfigurationResponse extends BaseResponse {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setDefaultValue(String defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
@ -100,4 +156,44 @@ public class ConfigurationResponse extends BaseResponse {
|
||||
this.isDynamic = isDynamic;
|
||||
}
|
||||
|
||||
public String getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
public void setComponent(String component) {
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
public String getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(String parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public String getDisplayText() {
|
||||
return displayText;
|
||||
}
|
||||
|
||||
public void setDisplayText(String displayText) {
|
||||
this.displayText = displayText;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOptions(String options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
// 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.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
public class ConfigurationSubGroupResponse extends BaseResponse {
|
||||
@SerializedName(ApiConstants.NAME)
|
||||
@Param(description = "the name of the configuration subgroup")
|
||||
private String subGroupName;
|
||||
|
||||
@SerializedName(ApiConstants.PRECEDENCE)
|
||||
@Param(description = "the precedence of the configuration subgroup")
|
||||
private Long precedence;
|
||||
|
||||
public String getSubGroupName() {
|
||||
return subGroupName;
|
||||
}
|
||||
|
||||
public void setSubGroupName(String subGroupName) {
|
||||
this.subGroupName = subGroupName;
|
||||
}
|
||||
|
||||
public Long getPrecedence() {
|
||||
return precedence;
|
||||
}
|
||||
|
||||
public void setPrecedence(Long precedence) {
|
||||
this.precedence = precedence;
|
||||
}
|
||||
}
|
||||
@ -44,12 +44,12 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
|
||||
ConfigKey<String> BackupProviderPlugin = new ConfigKey<>("Advanced", String.class,
|
||||
"backup.framework.provider.plugin",
|
||||
"dummy",
|
||||
"The backup and recovery provider plugin.", true, ConfigKey.Scope.Zone);
|
||||
"The backup and recovery provider plugin.", true, ConfigKey.Scope.Zone, BackupFrameworkEnabled.key());
|
||||
|
||||
ConfigKey<Long> BackupSyncPollingInterval = new ConfigKey<>("Advanced", Long.class,
|
||||
"backup.framework.sync.interval",
|
||||
"300",
|
||||
"The backup and recovery background sync task polling interval in seconds.", true);
|
||||
"The backup and recovery background sync task polling interval in seconds.", true, BackupFrameworkEnabled.key());
|
||||
|
||||
ConfigKey<Boolean> BackupEnableAttachDetachVolumes = new ConfigKey<>("Advanced", Boolean.class,
|
||||
"backup.enable.attach.detach.of.volumes",
|
||||
|
||||
@ -46,10 +46,10 @@ public interface CAManager extends CAService, Configurable, PluggableService {
|
||||
"2048",
|
||||
"The key size to be used for random certificate keypair generation.", true);
|
||||
|
||||
ConfigKey<String> CertSignatureAlgorithm = new ConfigKey<>("Advanced", String.class,
|
||||
"ca.framework.cert.signature.algorithm",
|
||||
ConfigKey<String> CertSignatureAlgorithm = new ConfigKey<>(String.class,
|
||||
"ca.framework.cert.signature.algorithm", "Advanced",
|
||||
"SHA256withRSA",
|
||||
"The default signature algorithm to use for certificate generation.", true);
|
||||
"The default signature algorithm to use for certificate generation.", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.Select, "SHA256withRSA");
|
||||
|
||||
|
||||
ConfigKey<Integer> CertValidityPeriod = new ConfigKey<>("Advanced", Integer.class,
|
||||
|
||||
@ -20,15 +20,15 @@ import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
|
||||
public class ApiServiceConfiguration implements Configurable {
|
||||
public static final ConfigKey<String> ManagementServerAddresses = new ConfigKey<String>("Advanced", String.class, "host", "localhost", "The ip address of management server. This can also accept comma separated addresses.", true);
|
||||
public static final ConfigKey<String> ManagementServerAddresses = new ConfigKey<>(String.class, "host", "Advanced", "localhost", "The ip address of management server. This can also accept comma separated addresses.", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
|
||||
public static final ConfigKey<String> ApiServletPath = new ConfigKey<String>("Advanced", String.class, "endpoint.url", "http://localhost:8080/client/api",
|
||||
"API end point. Can be used by CS components/services deployed remotely, for sending CS API requests", true);
|
||||
public static final ConfigKey<Long> DefaultUIPageSize = new ConfigKey<Long>("Advanced", Long.class, "default.ui.page.size", "20",
|
||||
"The default pagesize to be used by UI and other clients when making list* API calls", true, ConfigKey.Scope.Global);
|
||||
public static final ConfigKey<Boolean> ApiSourceCidrChecksEnabled = new ConfigKey<>("Advanced", Boolean.class, "api.source.cidr.checks.enabled",
|
||||
"true", "Are the source checks on API calls enabled (true) or not (false)? See api.allowed.source.cidr.list", true, ConfigKey.Scope.Global);
|
||||
public static final ConfigKey<String> ApiAllowedSourceCidrList = new ConfigKey<String>("Advanced", String.class, "api.allowed.source.cidr.list",
|
||||
"0.0.0.0/0,::/0", "Comma separated list of IPv4/IPv6 CIDRs from which API calls can be performed. Can be set on Global and Account levels.", true, ConfigKey.Scope.Account);
|
||||
public static final ConfigKey<String> ApiAllowedSourceCidrList = new ConfigKey<>(String.class, "api.allowed.source.cidr.list", "Advanced",
|
||||
"0.0.0.0/0,::/0", "Comma separated list of IPv4/IPv6 CIDRs from which API calls can be performed. Can be set on Global and Account levels.", true, ConfigKey.Scope.Account, null, null, null, null, null, ConfigKey.Kind.CSV, null);
|
||||
@Override
|
||||
public String getConfigComponentName() {
|
||||
return ApiServiceConfiguration.class.getSimpleName();
|
||||
|
||||
@ -94,13 +94,13 @@ public interface QueryService {
|
||||
ConfigKey<Boolean> AllowUserViewDestroyedVM = new ConfigKey<>("Advanced", Boolean.class, "allow.user.view.destroyed.vm", "false",
|
||||
"Determines whether users can view their destroyed or expunging vm ", true, ConfigKey.Scope.Account);
|
||||
|
||||
static final ConfigKey<String> UserVMDeniedDetails = new ConfigKey<String>("Advanced", String.class,
|
||||
"user.vm.denied.details", "rootdisksize, cpuOvercommitRatio, memoryOvercommitRatio, Message.ReservedCapacityFreed.Flag",
|
||||
"Determines whether users can view certain VM settings. When set to empty, default value used is: rootdisksize, cpuOvercommitRatio, memoryOvercommitRatio, Message.ReservedCapacityFreed.Flag.", true);
|
||||
static final ConfigKey<String> UserVMDeniedDetails = new ConfigKey<>(String.class,
|
||||
"user.vm.denied.details", "Advanced", "rootdisksize, cpuOvercommitRatio, memoryOvercommitRatio, Message.ReservedCapacityFreed.Flag",
|
||||
"Determines whether users can view certain VM settings. When set to empty, default value used is: rootdisksize, cpuOvercommitRatio, memoryOvercommitRatio, Message.ReservedCapacityFreed.Flag.", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
static final ConfigKey<String> UserVMReadOnlyDetails = new ConfigKey<String>("Advanced", String.class,
|
||||
"user.vm.readonly.details", "dataDiskController, rootDiskController",
|
||||
"List of read-only VM settings/details as comma separated string", true);
|
||||
static final ConfigKey<String> UserVMReadOnlyDetails = new ConfigKey<>(String.class,
|
||||
"user.vm.readonly.details", "Advanced", "dataDiskController, rootDiskController",
|
||||
"List of read-only VM settings/details as comma separated string", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
ConfigKey<Boolean> SortKeyAscending = new ConfigKey<>("Advanced", Boolean.class, "sortkey.algorithm", "true",
|
||||
"Sort algorithm - ascending or descending - to use. For entities that use sort key(template, disk offering, service offering, " +
|
||||
|
||||
@ -66,7 +66,7 @@ public interface VirtualMachineManager extends Manager {
|
||||
"If config drive need to be created and hosted on primary storage pool. Currently only supported for KVM.", true, ConfigKey.Scope.Zone);
|
||||
|
||||
ConfigKey<Boolean> VmConfigDriveUseHostCacheOnUnsupportedPool = new ConfigKey<>("Advanced", Boolean.class, "vm.configdrive.use.host.cache.on.unsupported.pool", "true",
|
||||
"If true, config drive is created on the host cache storage when vm.configdrive.primarypool.enabled is true and the primary pool type doesn't support config drive.", true, ConfigKey.Scope.Zone);
|
||||
"If true, config drive is created on the host cache storage when vm.configdrive.primarypool.enabled is true and the primary pool type doesn't support config drive.", true, ConfigKey.Scope.Zone, VmConfigDriveOnPrimaryPool.key());
|
||||
|
||||
ConfigKey<Boolean> VmConfigDriveForceHostCacheUse = new ConfigKey<>("Advanced", Boolean.class, "vm.configdrive.force.host.cache.use", "false",
|
||||
"If true, config drive is forced to create on the host cache storage. Currently only supported for KVM.", true, ConfigKey.Scope.Zone);
|
||||
|
||||
@ -20,6 +20,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO;
|
||||
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenter.NetworkType;
|
||||
@ -42,6 +44,7 @@ import com.cloud.offering.NetworkOffering.Availability;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
import com.cloud.org.Grouping.AllocationState;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
|
||||
/**
|
||||
@ -261,4 +264,10 @@ public interface ConfigurationManager {
|
||||
AllocationState findPodAllocationState(HostPodVO pod);
|
||||
|
||||
AllocationState findClusterAllocationState(ClusterVO cluster);
|
||||
|
||||
String getConfigurationType(String configName);
|
||||
|
||||
Pair<String, String> getConfigurationGroupAndSubGroup(String configName);
|
||||
|
||||
List<ConfigurationSubGroupVO> getConfigurationSubGroups(Long groupId);
|
||||
}
|
||||
|
||||
@ -49,11 +49,12 @@ public interface IpAddressManager {
|
||||
"When true, ip address delete (ipassoc) failures are ignored", true);
|
||||
|
||||
ConfigKey<String> VrouterRedundantTiersPlacement = new ConfigKey<String>(
|
||||
"Advanced", String.class,
|
||||
String.class,
|
||||
"vrouter.redundant.tiers.placement",
|
||||
"Advanced",
|
||||
"random",
|
||||
"Set placement of vrouter ips in redundant mode in vpc tiers, this can be 3 value: `first` to use first ips in tiers, `last` to use last ips in tiers and `random` to take random ips in tiers.",
|
||||
true, ConfigKey.Scope.Account);
|
||||
true, ConfigKey.Scope.Account, null, null, null, null, null, ConfigKey.Kind.Select, "first,last,random");
|
||||
|
||||
/**
|
||||
* Assigns a new public ip address.
|
||||
|
||||
@ -53,13 +53,13 @@ public interface ResourceManager extends ResourceService, Configurable {
|
||||
"Number of retries when preparing a host into Maintenance Mode is faulty before failing",
|
||||
false);
|
||||
|
||||
ConfigKey<String> HOST_MAINTENANCE_LOCAL_STRATEGY = new ConfigKey<>("Advanced", String.class,
|
||||
"host.maintenance.local.storage.strategy", "Error",
|
||||
ConfigKey<String> HOST_MAINTENANCE_LOCAL_STRATEGY = new ConfigKey<>(String.class,
|
||||
"host.maintenance.local.storage.strategy", "Advanced","Error",
|
||||
"Defines the strategy towards VMs with volumes on local storage when putting a host in maintenance. "
|
||||
+ "The default strategy is 'Error', preventing maintenance in such a case. "
|
||||
+ "Choose 'Migration' strategy to migrate away VMs running on local storage. "
|
||||
+ "To force-stop VMs, choose 'ForceStop' strategy",
|
||||
true, ConfigKey.Scope.Global);
|
||||
true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.Select, "Error,Migration,ForceStop");
|
||||
|
||||
/**
|
||||
* Register a listener for different types of resource life cycle events.
|
||||
|
||||
@ -45,22 +45,6 @@ import com.cloud.vm.DiskProfile;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
|
||||
public interface StorageManager extends StorageService {
|
||||
ConfigKey<Integer> StorageCleanupInterval = new ConfigKey<>(Integer.class,
|
||||
"storage.cleanup.interval",
|
||||
"Advanced",
|
||||
"86400",
|
||||
"The interval (in seconds) to wait before running the storage cleanup thread.",
|
||||
false,
|
||||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
ConfigKey<Integer> StorageCleanupDelay = new ConfigKey<>(Integer.class,
|
||||
"storage.cleanup.delay",
|
||||
"Advanced",
|
||||
"86400",
|
||||
"Determines how long (in seconds) to wait before actually expunging destroyed volumes. The default value = the default value of storage.cleanup.interval.",
|
||||
false,
|
||||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
ConfigKey<Boolean> StorageCleanupEnabled = new ConfigKey<>(Boolean.class,
|
||||
"storage.cleanup.enabled",
|
||||
"Advanced",
|
||||
@ -69,6 +53,24 @@ public interface StorageManager extends StorageService {
|
||||
false,
|
||||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
ConfigKey<Integer> StorageCleanupInterval = new ConfigKey<>(Integer.class,
|
||||
"storage.cleanup.interval",
|
||||
"Advanced",
|
||||
"86400",
|
||||
"The interval (in seconds) to wait before running the storage cleanup thread.",
|
||||
false,
|
||||
ConfigKey.Scope.Global,
|
||||
null,
|
||||
StorageCleanupEnabled.key());
|
||||
ConfigKey<Integer> StorageCleanupDelay = new ConfigKey<>(Integer.class,
|
||||
"storage.cleanup.delay",
|
||||
"Advanced",
|
||||
"86400",
|
||||
"Determines how long (in seconds) to wait before actually expunging destroyed volumes. The default value = the default value of storage.cleanup.interval.",
|
||||
false,
|
||||
ConfigKey.Scope.Global,
|
||||
null,
|
||||
StorageCleanupEnabled.key());
|
||||
ConfigKey<Boolean> TemplateCleanupEnabled = new ConfigKey<>(Boolean.class,
|
||||
"storage.template.cleanup.enabled",
|
||||
"Storage",
|
||||
@ -76,7 +78,8 @@ public interface StorageManager extends StorageService {
|
||||
"Enable/disable template cleanup activity, only take effect when overall storage cleanup is enabled",
|
||||
false,
|
||||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
null,
|
||||
StorageCleanupEnabled.key());
|
||||
ConfigKey<Integer> KvmStorageOfflineMigrationWait = new ConfigKey<>(Integer.class,
|
||||
"kvm.storage.offline.migration.wait",
|
||||
"Storage",
|
||||
|
||||
@ -136,7 +136,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
|
||||
|
||||
protected final ConfigKey<Boolean> EnableLB = new ConfigKey<Boolean>(Boolean.class, "agent.lb.enabled", "Advanced", "false", "Enable agent load balancing between management server nodes", true);
|
||||
protected final ConfigKey<Double> ConnectedAgentThreshold = new ConfigKey<Double>(Double.class, "agent.load.threshold", "Advanced", "0.7",
|
||||
"What percentage of the agents can be held by one management server before load balancing happens", true);
|
||||
"What percentage of the agents can be held by one management server before load balancing happens", true, EnableLB.key());
|
||||
protected final ConfigKey<Integer> LoadSize = new ConfigKey<Integer>(Integer.class, "direct.agent.load.size", "Advanced", "16", "How many agents to connect to in each round", true);
|
||||
protected final ConfigKey<Integer> ScanInterval = new ConfigKey<Integer>(Integer.class, "direct.agent.scan.interval", "Advanced", "90", "Interval between scans to load agents", false,
|
||||
ConfigKey.Scope.Global, 1000);
|
||||
|
||||
@ -0,0 +1,106 @@
|
||||
// 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 com.cloud.upgrade;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
public class ConfigurationGroupsAggregator {
|
||||
|
||||
static final Logger LOG = Logger.getLogger(ConfigurationGroupsAggregator.class);
|
||||
|
||||
@Inject
|
||||
ConfigurationDao configDao;
|
||||
@Inject
|
||||
ConfigurationGroupDao configGroupDao;
|
||||
@Inject
|
||||
ConfigurationSubGroupDao configSubGroupDao;
|
||||
|
||||
public ConfigurationGroupsAggregator() {
|
||||
configDao = new ConfigurationDaoImpl();
|
||||
configGroupDao = new ConfigurationGroupDaoImpl();
|
||||
configSubGroupDao = new ConfigurationSubGroupDaoImpl();
|
||||
}
|
||||
|
||||
public void updateConfigurationGroups() {
|
||||
LOG.debug("Updating configuration groups");
|
||||
List<ConfigurationVO> configs = configDao.listAllIncludingRemoved();
|
||||
if (CollectionUtils.isEmpty(configs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final ConfigurationVO config : configs) {
|
||||
String configName = config.getName();
|
||||
if (StringUtils.isBlank(configName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
Pair<Long, Long> configGroupAndSubGroup = getConfigurationGroupAndSubGroupByName(configName);
|
||||
if (configGroupAndSubGroup.first() != 1 && configGroupAndSubGroup.second() != 1) {
|
||||
config.setGroupId(configGroupAndSubGroup.first());
|
||||
config.setSubGroupId(configGroupAndSubGroup.second());
|
||||
configDao.persist(config);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to update group for configuration " + configName + " due to " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
LOG.debug("Successfully updated configuration groups.");
|
||||
}
|
||||
|
||||
private Pair<Long, Long> getConfigurationGroupAndSubGroupByName(String configName) {
|
||||
Long subGroupId = 1L;
|
||||
Long groupId = 1L;
|
||||
if (StringUtils.isNotBlank(configName)) {
|
||||
// Get words from the dot notation in the configuration
|
||||
String[] nameWords = configName.split("\\.");
|
||||
if (nameWords.length > 0) {
|
||||
for (int index = 0; index < nameWords.length; index++) {
|
||||
ConfigurationSubGroupVO configSubGroup = configSubGroupDao.findByName(nameWords[index]);
|
||||
|
||||
if (configSubGroup == null) {
|
||||
configSubGroup = configSubGroupDao.findByKeyword(nameWords[index]);
|
||||
}
|
||||
|
||||
if (configSubGroup != null) {
|
||||
subGroupId = configSubGroup.getId();
|
||||
groupId = configSubGroup.getGroupId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Pair<>(groupId, subGroupId);
|
||||
}
|
||||
}
|
||||
@ -16,11 +16,6 @@
|
||||
// under the License.
|
||||
package com.cloud.upgrade.dao;
|
||||
|
||||
import com.cloud.upgrade.SystemVmTemplateRegistration;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Connection;
|
||||
@ -29,6 +24,11 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.upgrade.SystemVmTemplateRegistration;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
public class Upgrade41610to41700 implements DbUpgrade, DbUpgradeSystemVmTemplate {
|
||||
|
||||
final static Logger LOG = Logger.getLogger(Upgrade41700to41710.class);
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
package com.cloud.upgrade.dao;
|
||||
|
||||
import com.cloud.storage.GuestOSHypervisorMapping;
|
||||
import com.cloud.upgrade.ConfigurationGroupsAggregator;
|
||||
import com.cloud.upgrade.GuestOsMapper;
|
||||
import com.cloud.upgrade.SystemVmTemplateRegistration;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
@ -45,6 +46,7 @@ public class Upgrade41720to41800 implements DbUpgrade, DbUpgradeSystemVmTemplate
|
||||
private GuestOsMapper guestOsMapper = new GuestOsMapper();
|
||||
|
||||
private SystemVmTemplateRegistration systemVmTemplateRegistration;
|
||||
private ConfigurationGroupsAggregator configGroupsAggregator = new ConfigurationGroupsAggregator();
|
||||
|
||||
@Override
|
||||
public String[] getUpgradableVersionRange() {
|
||||
@ -79,6 +81,7 @@ public class Upgrade41720to41800 implements DbUpgrade, DbUpgradeSystemVmTemplate
|
||||
correctGuestOsNames();
|
||||
updateGuestOsMappings();
|
||||
correctGuestOsIdsInHypervisorMapping(conn);
|
||||
updateConfigurationGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -702,4 +705,8 @@ public class Upgrade41720to41800 implements DbUpgrade, DbUpgradeSystemVmTemplate
|
||||
LOG.debug("Correcting guest OS ids in hypervisor mappings");
|
||||
guestOsMapper.updateGuestOsIdInHypervisorMapping(conn, 10, "Ubuntu 20.04 LTS", new GuestOSHypervisorMapping("Xenserver", "8.2.0", "Ubuntu Focal Fossa 20.04"));
|
||||
}
|
||||
|
||||
private void updateConfigurationGroups() {
|
||||
configGroupsAggregator.updateConfigurationGroups();
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +61,8 @@
|
||||
<bean id="commandExecLogDaoImpl" class="com.cloud.secstorage.CommandExecLogDaoImpl" />
|
||||
<bean id="conditionDaoImpl" class="com.cloud.network.as.dao.ConditionDaoImpl" />
|
||||
<bean id="consoleProxyDaoImpl" class="com.cloud.vm.dao.ConsoleProxyDaoImpl" />
|
||||
<bean id="configurationGroupDaoImpl" class="org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl" />
|
||||
<bean id="configurationSubGroupDaoImpl" class="org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl" />
|
||||
<bean id="counterDaoImpl" class="com.cloud.network.as.dao.CounterDaoImpl" />
|
||||
<bean id="dataCenterJoinDaoImpl" class="com.cloud.api.query.dao.DataCenterJoinDaoImpl" />
|
||||
<bean id="domainVlanMapDaoImpl" class="com.cloud.dc.dao.DomainVlanMapDaoImpl" />
|
||||
|
||||
@ -26,8 +26,6 @@ ALTER TABLE cloud.remote_access_vpn MODIFY ipsec_psk text NOT NULL;
|
||||
-- PR#5832 Fix 'endpointe.url' global settings configuration typo.
|
||||
UPDATE `cloud`.`configuration` SET name='endpoint.url' WHERE name='endpointe.url';
|
||||
|
||||
|
||||
|
||||
ALTER TABLE `cloud`.`service_offering` ADD COLUMN `uuid` varchar(40) UNIQUE DEFAULT NULL;
|
||||
ALTER TABLE `cloud`.`service_offering` ADD COLUMN `name` varchar(255) NOT NULL;
|
||||
ALTER TABLE `cloud`.`service_offering` ADD COLUMN `display_text` varchar(4096) DEFAULT NULL ;
|
||||
@ -592,7 +590,7 @@ CREATE TABLE `cloud`.`vm_stats` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- PR#5984 Update name for global configuration vm.stats.increment.metrics
|
||||
Update configuration set name='vm.stats.increment.metrics' where name='vm.stats.increment.metrics.in.memory';
|
||||
UPDATE `cloud`.`configuration` SET name = 'vm.stats.increment.metrics' WHERE name = 'vm.stats.increment.metrics.in.memory';
|
||||
|
||||
ALTER TABLE `cloud`.`domain_router` ADD COLUMN `software_version` varchar(100) COMMENT 'Software version';
|
||||
|
||||
@ -970,4 +968,4 @@ WHERE not exists( SELECT 1
|
||||
;END;
|
||||
|
||||
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (2, 'Debian GNU/Linux 11 (64-bit)', 'XenServer', '8.2.1', 'Debian Bullseye 11');
|
||||
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (2, 'Debian GNU/Linux 11 (32-bit)', 'XenServer', '8.2.1', 'Debian Bullseye 11');
|
||||
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (2, 'Debian GNU/Linux 11 (32-bit)', 'XenServer', '8.2.1', 'Debian Bullseye 11');
|
||||
@ -219,12 +219,12 @@ CREATE TABLE IF NOT EXISTS `cloud`.`passphrase` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- Add passphrase column to volumes table
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.volumes', 'passphrase_id', 'bigint unsigned DEFAULT NULL COMMENT ''encryption passphrase id'' ');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.volumes', 'passphrase_id', 'bigint unsigned DEFAULT NULL COMMENT "encryption passphrase id" ');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_FOREIGN_KEY`('cloud.volumes', 'passphrase', 'id');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.volumes', 'encrypt_format', 'varchar(64) DEFAULT NULL COMMENT ''encryption format'' ');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.volumes', 'encrypt_format', 'varchar(64) DEFAULT NULL COMMENT "encryption format" ');
|
||||
|
||||
-- Add encrypt column to disk_offering
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.disk_offering', 'encrypt', 'tinyint(1) DEFAULT 0 COMMENT ''volume encrypt requested'' ');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.disk_offering', 'encrypt', 'tinyint(1) DEFAULT 0 COMMENT "volume encrypt requested" ');
|
||||
|
||||
-- add encryption support to disk offering view
|
||||
DROP VIEW IF EXISTS `cloud`.`disk_offering_view`;
|
||||
@ -1101,6 +1101,249 @@ INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`)
|
||||
SELECT UUID(), `roles`.`id`, 'isAccountAllowedToCreateOfferingsWithTags', 'ALLOW'
|
||||
FROM `cloud`.`roles` WHERE `role_type` = 'DomainAdmin';
|
||||
|
||||
--
|
||||
-- Update Configuration Groups and Subgroups
|
||||
--
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.configuration', 'group_id', 'bigint unsigned DEFAULT 1 COMMENT "group id this configuration belongs to" ');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.configuration', 'subgroup_id', 'bigint unsigned DEFAULT 1 COMMENT "subgroup id this configuration belongs to" ');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.configuration', 'parent', 'VARCHAR(255) DEFAULT NULL COMMENT "name of the parent configuration if this depends on it" ');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.configuration', 'display_text', 'VARCHAR(255) DEFAULT NULL COMMENT "Short text about configuration to display to the users" ');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.configuration', 'kind', 'VARCHAR(255) DEFAULT NULL COMMENT "kind of the value such as order, csv, etc" ');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.configuration', 'options', 'VARCHAR(255) DEFAULT NULL COMMENT "possible options for the value" ');
|
||||
|
||||
CREATE TABLE `cloud`.`configuration_group` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`name` varchar(255) NOT NULL COMMENT 'name of the configuration group',
|
||||
`description` varchar(1024) DEFAULT NULL COMMENT 'description of the configuration group',
|
||||
`precedence` bigint(20) unsigned DEFAULT '999' COMMENT 'precedence for the configuration group',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `cloud`.`configuration_subgroup` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`name` varchar(255) NOT NULL COMMENT 'name of the configuration subgroup',
|
||||
`keywords` varchar(4096) DEFAULT NULL COMMENT 'comma-separated keywords for the configuration subgroup',
|
||||
`precedence` bigint(20) unsigned DEFAULT '999' COMMENT 'precedence for the configuration subgroup',
|
||||
`group_id` bigint(20) unsigned NOT NULL COMMENT 'configuration group id',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY (`name`, `group_id`),
|
||||
CONSTRAINT `fk_configuration_subgroup__group_id` FOREIGN KEY (`group_id`) REFERENCES `configuration_group` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
ALTER TABLE `cloud`.`configuration_group` AUTO_INCREMENT=1;
|
||||
|
||||
INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Miscellaneous', 'Miscellaneous configuration', 999);
|
||||
INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Access', 'Identity and Access management configuration', 1);
|
||||
INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Compute', 'Compute configuration', 2);
|
||||
INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Storage', 'Storage configuration', 3);
|
||||
INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Network', 'Network configuration', 4);
|
||||
INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Hypervisor', 'Hypervisor specific configuration', 5);
|
||||
INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Management Server', 'Management Server configuration', 6);
|
||||
INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('System VMs', 'System VMs related configuration', 7);
|
||||
INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Infrastructure', 'Infrastructure configuration', 8);
|
||||
|
||||
ALTER TABLE `cloud`.`configuration_subgroup` AUTO_INCREMENT=1;
|
||||
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Others', NULL, 999, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Miscellaneous'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Account', NULL, 1, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Access'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Domain', NULL, 2, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Access'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Project', NULL, 3, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Access'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('LDAP', NULL, 4, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Access'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('SAML', 'saml2', 5, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Access'));
|
||||
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Virtual Machine', 'vm,instance,cpu,ssh,affinity', 1, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Compute'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Kubernetes', 'kubernetes', 2, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Compute'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('High Availability', 'ha', 3, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Compute'));
|
||||
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Images', 'template,iso', 1, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Storage'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Volume', 'disk,diskoffering', 2, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Storage'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Snapshot', NULL, 3, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Storage'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('VM Snapshot', 'vmsnapshot', 4, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Storage'));
|
||||
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Network', 'firewall,vlan,dns,globodns,ipaddress,cidr', 1, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Network'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('DHCP', 'externaldhcp', 2, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Network'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('VPC', NULL, 3, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Network'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('LoadBalancer', 'lb,gslb', 4, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Network'));
|
||||
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('API', NULL, 1, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Management Server'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Alerts', 'alert', 2, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Management Server'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Events', 'event', 3, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Management Server'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Security', 'secure,password,authenticators', 4, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Management Server'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Usage', NULL, 5, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Management Server'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Limits', 'capacity,delay,interval,workers', 6, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Management Server'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Jobs', 'job', 7, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Management Server'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Agent', NULL, 8, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Management Server'));
|
||||
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Hypervisor', 'host', 1, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Hypervisor'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('KVM', 'libvirt', 2, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Hypervisor'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('VMware', 'vcenter', 3, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Hypervisor'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('XenServer', 'xen,xapi,XCP', 4, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Hypervisor'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('OVM', 'ovm3', 5, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Hypervisor'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Baremetal', NULL, 6, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Hypervisor'));
|
||||
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('ConsoleProxyVM', 'cpvm,consoleproxy,novnc', 1, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'System VMs'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('SecStorageVM', 'ssvm,secondary', 2, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'System VMs'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('VirtualRouter', 'vr,router,vrouter', 3, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'System VMs'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Diagnostics', NULL, 4, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'System VMs'));
|
||||
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Primary Storage', 'storage,pool,primary', 1, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Infrastructure'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Secondary Storage', 'image,secstorage', 2, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Infrastructure'));
|
||||
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Backup & Recovery', 'backup,recovery,veeam', 1, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Miscellaneous'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Certificate Authority', 'CA', 2, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Miscellaneous'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Quota', NULL, 3, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Miscellaneous'));
|
||||
INSERT INTO `cloud`.`configuration_subgroup` (`name`, `keywords`, `precedence`, `group_id`) VALUES ('Cloudian', NULL, 4, (SELECT id FROM `cloud`.`configuration_group` WHERE `name` = 'Miscellaneous'));
|
||||
|
||||
UPDATE `cloud`.`configuration` SET parent = 'agent.lb.enabled' WHERE name IN ('agent.load.threshold');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'indirect.agent.lb.check.interval' WHERE name IN ('indirect.agent.lb.algorithm');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'alert.purge.delay' WHERE name IN ('alert.purge.interval');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'api.throttling.enabled' WHERE name IN ('api.throttling.cachesize', 'api.throttling.interval', 'api.throttling.max');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'backup.framework.enabled' WHERE name IN ('backup.framework.provider.plugin', 'backup.framework.sync.interval');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'cloud.kubernetes.service.enabled' WHERE name IN ('cloud.kubernetes.cluster.max.size', 'cloud.kubernetes.cluster.network.offering', 'cloud.kubernetes.cluster.scale.timeout', 'cloud.kubernetes.cluster.start.timeout', 'cloud.kubernetes.cluster.upgrade.timeout', 'cloud.kubernetes.cluster.experimental.features.enabled');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'diagnostics.data.gc.enable' WHERE name IN ('diagnostics.data.gc.interval', 'diagnostics.data.max.file.age');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'enable.additional.vm.configuration' WHERE name IN ('allow.additional.vm.configuration.list.kvm', 'allow.additional.vm.configuration.list.vmware', 'allow.additional.vm.configuration.list.xenserver');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'event.purge.delay' WHERE name IN ('event.purge.interval');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'network.loadbalancer.basiczone.elb.enabled' WHERE name IN ('network.loadbalancer.basiczone.elb.network', 'network.loadbalancer.basiczone.elb.vm.cpu.mhz', 'network.loadbalancer.basiczone.elb.vm.ram.size', 'network.loadbalancer.basiczone.elb.vm.vcpu.num', 'network.loadbalancer.basiczone.elb.gc.interval.minutes');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'prometheus.exporter.enable' WHERE name IN ('prometheus.exporter.port', 'prometheus.exporter.allowed.ips');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'router.health.checks.enable' WHERE name IN ('router.health.checks.basic.interval', 'router.health.checks.advanced.interval', 'router.health.checks.config.refresh.interval', 'router.health.checks.results.fetch.interval', 'router.health.checks.to.exclude', 'router.health.checks.failures.to.recreate.vr', 'router.health.checks.free.disk.space.threshold', 'router.health.checks.max.cpu.usage.threshold', 'router.health.checks.max.memory.usage.threshold');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'storage.cache.replacement.enabled' WHERE name IN ('storage.cache.replacement.interval', 'storage.cache.replacement.lru.interval');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'storage.cleanup.enabled' WHERE name IN ('storage.cleanup.interval', 'storage.cleanup.delay', 'storage.template.cleanup.enabled');
|
||||
UPDATE `cloud`.`configuration` SET parent = 'vm.configdrive.primarypool.enabled' WHERE name IN ('vm.configdrive.use.host.cache.on.unsupported.pool');
|
||||
|
||||
UPDATE `cloud`.`configuration` SET display_text = CONCAT(UCASE(LEFT(REPLACE(name, ".", " "), 1)), LCASE(SUBSTRING(REPLACE(name, ".", " "), 2)));
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Order',
|
||||
`options` = 'HostAntiAffinityProcessor,ExplicitDedicationProcessor,HostAffinityProcessor'
|
||||
where `name` = 'affinity.processors.order' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Order',
|
||||
`options` = 'FirstFitPlanner,UserDispersingPlanner,UserConcentratedPodPlanner,ImplicitDedicationPlanner,BareMetalPlanner'
|
||||
where `name` = 'deployment.planners.order' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Order',
|
||||
`options` = 'SimpleInvestigator,XenServerInvestigator,KVMInvestigator,HypervInvestigator,VMwareInvestigator,PingInvestigator,ManagementIPSysVMInvestigator,Ovm3Investigator'
|
||||
where `name` = 'ha.investigators.order' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Order',
|
||||
`options` = 'FirstFitRouting'
|
||||
where `name` = 'host.allocators.order' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Order',
|
||||
`options` = 'SAML2Auth'
|
||||
where `name` = 'pluggableApi.authenticators.order' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Order',
|
||||
`options` = 'AffinityGroupAccessChecker,DomainChecker'
|
||||
where `name` = 'security.checkers.order' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Order',
|
||||
`options` = 'LocalStorage,ClusterScopeStoragePoolAllocator,ZoneWideStoragePoolAllocator'
|
||||
where `name` = 'storage.pool.allocators.order' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Order',
|
||||
`options` = 'PBKDF2,SHA256SALT,MD5,LDAP,SAML2,PLAINTEXT'
|
||||
where `name` = 'user.authenticators.order' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Order',
|
||||
`options` = 'PBKDF2,SHA256SALT,MD5,LDAP,SAML2,PLAINTEXT'
|
||||
where `name` = 'user.password.encoders.order' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'CSV'
|
||||
where `name` like "%.list" ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'CSV'
|
||||
where `name` like "%.defaults" ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'CSV'
|
||||
where `name` like "%.details" ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'CSV'
|
||||
where `name` like "%.exclude" ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'CSV'
|
||||
where `name` IN ("alert.email.addresses", "allow.additional.vm.configuration.list.kvm", "allow.additional.vm.configuration.list.xenserver", "host",
|
||||
"network.dhcp.nondefaultnetwork.setgateway.guestos", "router.health.checks.failures.to.recreate.vr", "router.health.checks.to.exclude") ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'Error,Migration,ForceStop'
|
||||
where `name` = 'host.maintenance.local.storage.strategy' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'SHA256withRSA'
|
||||
where `name` = 'ca.framework.cert.signature.algorithm' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'firstfitleastconsumed,random'
|
||||
where `name` = 'image.store.allocation.algorithm' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'static,roundrobin,shuffle'
|
||||
where `name` = 'indirect.agent.lb.algorithm' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'random,firstfit,userdispersing,userconcentratedpod_random,userconcentratedpod_firstfit,firstfitleastconsumed'
|
||||
where `name` = 'vm.allocation.algorithm' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'all,pod'
|
||||
where `name` = 'network.dns.basiczone.updates' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'global,guest-network,link-local,disabled,all,default'
|
||||
where `name` = 'network.loadbalancer.haproxy.stats.visibility' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'SHA1,SHA256,SHA384,SHA512'
|
||||
where `name` = 'saml2.sigalg' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'FirstFitPlanner,UserDispersingPlanner,UserConcentratedPodPlanner'
|
||||
where `name` = 'vm.deployment.planner' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'scsi,ide,osdefault'
|
||||
where `name` = 'vmware.root.disk.controller' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'E1000,PCNet32,Vmxnet2,Vmxnet3'
|
||||
where `name` = 'vmware.systemvm.nic.device.type' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'first,last,random'
|
||||
where `name` = 'vrouter.redundant.tiers.placement' ;
|
||||
|
||||
UPDATE `cloud`.`configuration` SET
|
||||
`kind` = 'Select',
|
||||
`options` = 'xenserver56,xenserver61'
|
||||
where `name` = 'xenserver.pvdriver.version' ;
|
||||
|
||||
--- Create table for handling console sessions #7094
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cloud`.`console_session` (
|
||||
|
||||
@ -65,8 +65,8 @@ public class ImageStoreProviderManagerImpl implements ImageStoreProviderManager,
|
||||
|
||||
Map<String, ImageStoreDriver> driverMaps;
|
||||
|
||||
static final ConfigKey<String> ImageStoreAllocationAlgorithm = new ConfigKey<String>("Advanced", String.class, "image.store.allocation.algorithm", "firstfitleastconsumed",
|
||||
"firstfitleastconsumed','random' : Order in which hosts within a cluster will be considered for VM/volume allocation", true, ConfigKey.Scope.Global );
|
||||
static final ConfigKey<String> ImageStoreAllocationAlgorithm = new ConfigKey<>(String.class, "image.store.allocation.algorithm", "Advanced", "firstfitleastconsumed",
|
||||
"firstfitleastconsumed','random' : Order in which hosts within a cluster will be considered for VM/volume allocation", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.Select, "firstfitleastconsumed,random" );
|
||||
|
||||
@PostConstruct
|
||||
public void config() {
|
||||
|
||||
@ -33,6 +33,8 @@ import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationSer
|
||||
import org.apache.cloudstack.engine.service.api.OrchestrationService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl;
|
||||
import org.apache.cloudstack.framework.rpc.RpcProvider;
|
||||
import org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl;
|
||||
import org.apache.cloudstack.storage.test.ChildTestConfiguration.Library;
|
||||
@ -96,12 +98,12 @@ import com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl;
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = {NicDaoImpl.class, VMInstanceDaoImpl.class, VolumeDaoImpl.class,
|
||||
VMTemplatePoolDaoImpl.class, ResourceTagsDaoImpl.class, VMTemplateDaoImpl.class, MockStorageMotionStrategy.class, ConfigurationDaoImpl.class,
|
||||
ClusterDaoImpl.class, HostPodDaoImpl.class, VMTemplateZoneDaoImpl.class, VMTemplateDetailsDaoImpl.class, HostDetailsDaoImpl.class,
|
||||
HostTagsDaoImpl.class, HostTransferMapDaoImpl.class, DataCenterIpAddressDaoImpl.class, DataCenterLinkLocalIpAddressDaoImpl.class,
|
||||
DataCenterVnetDaoImpl.class, PodVlanDaoImpl.class, DataCenterDetailsDaoImpl.class, DiskOfferingDaoImpl.class, StoragePoolHostDaoImpl.class,
|
||||
UserVmDaoImpl.class, UserVmDetailsDaoImpl.class, ServiceOfferingDaoImpl.class, CapacityDaoImpl.class, SnapshotDaoImpl.class, VMSnapshotDaoImpl.class,
|
||||
OCFS2ManagerImpl.class, ClusterDetailsDaoImpl.class, SecondaryStorageVmDaoImpl.class, ConsoleProxyDaoImpl.class, StoragePoolWorkDaoImpl.class,
|
||||
StorageCacheManagerImpl.class, UserDaoImpl.class, DataCenterDaoImpl.class, StoragePoolDetailsDaoImpl.class, DomainDaoImpl.class,
|
||||
ConfigurationGroupDaoImpl.class, ConfigurationSubGroupDaoImpl.class, ClusterDaoImpl.class, HostPodDaoImpl.class, VMTemplateZoneDaoImpl.class,
|
||||
VMTemplateDetailsDaoImpl.class, HostDetailsDaoImpl.class, HostTagsDaoImpl.class, HostTransferMapDaoImpl.class, DataCenterIpAddressDaoImpl.class,
|
||||
DataCenterLinkLocalIpAddressDaoImpl.class, DataCenterVnetDaoImpl.class, PodVlanDaoImpl.class, DataCenterDetailsDaoImpl.class, DiskOfferingDaoImpl.class,
|
||||
StoragePoolHostDaoImpl.class, UserVmDaoImpl.class, UserVmDetailsDaoImpl.class, ServiceOfferingDaoImpl.class, CapacityDaoImpl.class, SnapshotDaoImpl.class,
|
||||
VMSnapshotDaoImpl.class, OCFS2ManagerImpl.class, ClusterDetailsDaoImpl.class, SecondaryStorageVmDaoImpl.class, ConsoleProxyDaoImpl.class,
|
||||
StoragePoolWorkDaoImpl.class, StorageCacheManagerImpl.class, UserDaoImpl.class, DataCenterDaoImpl.class, StoragePoolDetailsDaoImpl.class, DomainDaoImpl.class,
|
||||
DownloadMonitorImpl.class, AccountDaoImpl.class, ActionEventUtils.class, EventDaoImpl.class},
|
||||
includeFilters = {@Filter(value = Library.class, type = FilterType.CUSTOM)},
|
||||
useDefaultFilters = false)
|
||||
|
||||
@ -188,5 +188,9 @@
|
||||
-->
|
||||
<bean id="configurationDaoImpl" class="com.cloud.configuration.dao.ConfigurationDaoImpl">
|
||||
</bean>
|
||||
|
||||
<bean id="configurationGroupDaoImpl" class="com.cloud.configuration.dao.ConfigurationGroupDaoImpl">
|
||||
</bean>
|
||||
<bean id="configurationSubGroupDaoImpl" class="com.cloud.configuration.dao.ConfigurationSubGroupDaoImpl">
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
@ -22,9 +22,17 @@ import java.util.Date;
|
||||
* Configuration represents one global configuration parameter for CloudStack.
|
||||
* Its scope should indicate whether this parameter can be set at different
|
||||
* organization levels in CloudStack.
|
||||
*
|
||||
*/
|
||||
public interface Configuration {
|
||||
enum ValueType {
|
||||
Boolean,
|
||||
Number,
|
||||
Decimal,
|
||||
Range, // Min and Max (Percentage - 0 to 100)
|
||||
String,
|
||||
List, // Set of values
|
||||
Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Category of the parameter.
|
||||
@ -83,8 +91,25 @@ public interface Configuration {
|
||||
Date getUpdated();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return returns true if the configuration is encrypted else false.
|
||||
*/
|
||||
boolean isEncrypted();
|
||||
|
||||
/**
|
||||
* @return Parent of the configuration.
|
||||
*/
|
||||
String getParent();
|
||||
|
||||
/**
|
||||
* @return Display text of the configuration.
|
||||
*/
|
||||
String getDisplayText();
|
||||
|
||||
Long getGroupId();
|
||||
|
||||
Long getSubGroupId();
|
||||
|
||||
String getKind();
|
||||
|
||||
String getOptions();
|
||||
}
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
// 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.config;
|
||||
|
||||
public interface ConfigurationGroup {
|
||||
|
||||
long getId();
|
||||
|
||||
String getName();
|
||||
|
||||
String getDescription();
|
||||
|
||||
Long getPrecedence();
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
// 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.config;
|
||||
|
||||
public interface ConfigurationSubGroup {
|
||||
|
||||
public long getId();
|
||||
|
||||
public String getName();
|
||||
|
||||
public String getKeywords();
|
||||
|
||||
public Long getPrecedence();
|
||||
|
||||
public Long getGroupId();
|
||||
}
|
||||
@ -18,6 +18,8 @@ package org.apache.cloudstack.framework.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
/**
|
||||
* Administrative interface to ConfigDepot
|
||||
*
|
||||
@ -35,4 +37,6 @@ public interface ConfigDepotAdmin {
|
||||
void populateConfiguration(Configurable configurable);
|
||||
|
||||
List<String> getComponentsInDepot();
|
||||
|
||||
Pair<Long, Long> getConfigurationGroupAndSubGroupByName(String configName);
|
||||
}
|
||||
|
||||
@ -21,6 +21,8 @@ import java.sql.Date;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
/**
|
||||
@ -33,10 +35,14 @@ public class ConfigKey<T> {
|
||||
public static final String CATEGORY_ADVANCED = "Advanced";
|
||||
public static final String CATEGORY_ALERT = "Alert";
|
||||
|
||||
public static enum Scope {
|
||||
public enum Scope {
|
||||
Global, Zone, Cluster, StoragePool, Account, ManagementServer, ImageStore, Domain
|
||||
}
|
||||
|
||||
public enum Kind {
|
||||
CSV, Order, Select
|
||||
}
|
||||
|
||||
private final String _category;
|
||||
|
||||
public String category() {
|
||||
@ -59,6 +65,10 @@ public class ConfigKey<T> {
|
||||
return _description;
|
||||
}
|
||||
|
||||
public String displayText() {
|
||||
return _displayText;
|
||||
}
|
||||
|
||||
public Scope scope() {
|
||||
return _scope;
|
||||
}
|
||||
@ -67,6 +77,26 @@ public class ConfigKey<T> {
|
||||
return _isDynamic;
|
||||
}
|
||||
|
||||
public Ternary<String, String, Long> group() {
|
||||
return _group;
|
||||
}
|
||||
|
||||
public Pair<String, Long> subGroup() {
|
||||
return _subGroup;
|
||||
}
|
||||
|
||||
public final String parent() {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
public final Kind kind() {
|
||||
return _kind;
|
||||
}
|
||||
|
||||
public final String options() {
|
||||
return _options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return _name;
|
||||
@ -76,8 +106,14 @@ public class ConfigKey<T> {
|
||||
private final String _name;
|
||||
private final String _defaultValue;
|
||||
private final String _description;
|
||||
private final String _displayText;
|
||||
private final Scope _scope; // Parameter can be at different levels (Zone/cluster/pool/account), by default every parameter is at global
|
||||
private final boolean _isDynamic;
|
||||
private final String _parent;
|
||||
private final Ternary<String, String, Long> _group; // Group name, description with precedence
|
||||
private final Pair<String, Long> _subGroup; // SubGroup name with precedence
|
||||
private final Kind _kind; // Kind such as order, csv, etc
|
||||
private final String _options; // list of possible options in case of order, list, etc
|
||||
private final T _multiplier;
|
||||
T _value = null;
|
||||
|
||||
@ -91,19 +127,47 @@ public class ConfigKey<T> {
|
||||
this(type, name, category, defaultValue, description, isDynamic, scope, null);
|
||||
}
|
||||
|
||||
public ConfigKey(String category, Class<T> type, String name, String defaultValue, String description, boolean isDynamic, Scope scope, String parent) {
|
||||
this(type, name, category, defaultValue, description, isDynamic, scope, null, null, parent, null, null, null, null);
|
||||
}
|
||||
|
||||
public ConfigKey(String category, Class<T> type, String name, String defaultValue, String description, boolean isDynamic) {
|
||||
this(type, name, category, defaultValue, description, isDynamic, Scope.Global, null);
|
||||
}
|
||||
|
||||
public ConfigKey(String category, Class<T> type, String name, String defaultValue, String description, boolean isDynamic, String parent) {
|
||||
this(type, name, category, defaultValue, description, isDynamic, Scope.Global, null, null, parent, null, null, null, null);
|
||||
}
|
||||
|
||||
public ConfigKey(Class<T> type, String name, String category, String defaultValue, String description, boolean isDynamic, Scope scope, T multiplier) {
|
||||
this(type, name, category, defaultValue, description, isDynamic, scope, multiplier, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public ConfigKey(Class<T> type, String name, String category, String defaultValue, String description, boolean isDynamic, Scope scope, T multiplier, String parent) {
|
||||
this(type, name, category, defaultValue, description, isDynamic, scope, multiplier, null, parent, null, null, null, null);
|
||||
}
|
||||
|
||||
public ConfigKey(Class<T> type, String name, String category, String defaultValue, String description, boolean isDynamic, Scope scope, T multiplier,
|
||||
String displayText, String parent, Ternary<String, String, Long> group, Pair<String, Long> subGroup) {
|
||||
this(type, name, category, defaultValue, description, isDynamic, scope, multiplier, null, parent, null, null, null, null);
|
||||
}
|
||||
|
||||
public ConfigKey(Class<T> type, String name, String category, String defaultValue, String description, boolean isDynamic, Scope scope, T multiplier,
|
||||
String displayText, String parent, Ternary<String, String, Long> group, Pair<String, Long> subGroup, Kind kind, String options) {
|
||||
_category = category;
|
||||
_type = type;
|
||||
_name = name;
|
||||
_defaultValue = defaultValue;
|
||||
_description = description;
|
||||
_displayText = displayText;
|
||||
_scope = scope;
|
||||
_isDynamic = isDynamic;
|
||||
_multiplier = multiplier;
|
||||
_parent = parent;
|
||||
_group = group;
|
||||
_subGroup = subGroup;
|
||||
_kind = kind;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ -111,6 +175,10 @@ public class ConfigKey<T> {
|
||||
this(type, name, category, defaultValue, description, isDynamic, Scope.Global, null);
|
||||
}
|
||||
|
||||
public ConfigKey(Class<T> type, String name, String category, String defaultValue, String description, boolean isDynamic, String parent) {
|
||||
this(type, name, category, defaultValue, description, isDynamic, Scope.Global, null, null, parent, null, null);
|
||||
}
|
||||
|
||||
public T multiplier() {
|
||||
return _multiplier;
|
||||
}
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
// 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.dao;
|
||||
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationGroupVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface ConfigurationGroupDao extends GenericDao<ConfigurationGroupVO, Long> {
|
||||
ConfigurationGroupVO findByName(String name);
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
// 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.dao;
|
||||
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationGroupVO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
@Component
|
||||
public class ConfigurationGroupDaoImpl extends GenericDaoBase<ConfigurationGroupVO, Long> implements ConfigurationGroupDao {
|
||||
|
||||
final SearchBuilder<ConfigurationGroupVO> nameSearch;
|
||||
|
||||
public ConfigurationGroupDaoImpl() {
|
||||
super();
|
||||
|
||||
nameSearch = createSearchBuilder();
|
||||
nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationGroupVO findByName(String name) {
|
||||
SearchCriteria<ConfigurationGroupVO> sc = nameSearch.create();
|
||||
sc.setParameters("name", name);
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
// 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.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface ConfigurationSubGroupDao extends GenericDao<ConfigurationSubGroupVO, Long> {
|
||||
ConfigurationSubGroupVO findByName(String name);
|
||||
ConfigurationSubGroupVO startsWithName(String name);
|
||||
ConfigurationSubGroupVO findByKeyword(String keyword);
|
||||
ConfigurationSubGroupVO findByNameAndGroup(String name, Long groupId);
|
||||
List<ConfigurationSubGroupVO> findByGroup(Long groupId);
|
||||
}
|
||||
@ -0,0 +1,131 @@
|
||||
// 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.dao;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
@Component
|
||||
public class ConfigurationSubGroupDaoImpl extends GenericDaoBase<ConfigurationSubGroupVO, Long> implements ConfigurationSubGroupDao {
|
||||
|
||||
final SearchBuilder<ConfigurationSubGroupVO> nameSearch;
|
||||
final SearchBuilder<ConfigurationSubGroupVO> groupSearch;
|
||||
final SearchBuilder<ConfigurationSubGroupVO> nameAndGroupSearch;
|
||||
final SearchBuilder<ConfigurationSubGroupVO> keywordSearch;
|
||||
|
||||
public ConfigurationSubGroupDaoImpl() {
|
||||
super();
|
||||
|
||||
nameSearch = createSearchBuilder();
|
||||
nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.LIKE);
|
||||
nameSearch.done();
|
||||
|
||||
groupSearch = createSearchBuilder();
|
||||
groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
|
||||
groupSearch.done();
|
||||
|
||||
nameAndGroupSearch = createSearchBuilder();
|
||||
nameAndGroupSearch.and("name", nameAndGroupSearch.entity().getName(), SearchCriteria.Op.EQ);
|
||||
nameAndGroupSearch.and("groupId", nameAndGroupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
|
||||
nameAndGroupSearch.done();
|
||||
|
||||
keywordSearch = createSearchBuilder();
|
||||
keywordSearch.and("keywords", keywordSearch.entity().getKeywords(), SearchCriteria.Op.NNULL);
|
||||
keywordSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationSubGroupVO findByName(String name) {
|
||||
SearchCriteria<ConfigurationSubGroupVO> sc = nameSearch.create();
|
||||
sc.setParameters("name", name);
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationSubGroupVO startsWithName(String name) {
|
||||
SearchCriteria<ConfigurationSubGroupVO> sc = nameSearch.create();
|
||||
sc.setParameters("name", name + "%");
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
|
||||
private ConfigurationSubGroupVO matchKeywordBy(BiPredicate<String, String> matcher, List<ConfigurationSubGroupVO> configurationSubGroups, String keyword) {
|
||||
for (ConfigurationSubGroupVO configurationSubGroup : configurationSubGroups) {
|
||||
if (StringUtils.isBlank(configurationSubGroup.getKeywords())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] configKeywords = configurationSubGroup.getKeywords().split(",");
|
||||
if (configKeywords.length <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> keywords = Arrays.asList(configKeywords);
|
||||
for (String configKeyword : keywords) {
|
||||
if (StringUtils.isNotBlank(configKeyword)) {
|
||||
configKeyword = configKeyword.strip().toLowerCase();
|
||||
if (matcher.test(keyword, configKeyword)) {
|
||||
return configurationSubGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationSubGroupVO findByKeyword(String keyword) {
|
||||
if (StringUtils.isBlank(keyword)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SearchCriteria<ConfigurationSubGroupVO> sc = keywordSearch.create();
|
||||
List<ConfigurationSubGroupVO> configurationSubGroups = listBy(sc);
|
||||
BiPredicate<String, String> equals = (a, b) -> { return a.equalsIgnoreCase(b); };
|
||||
ConfigurationSubGroupVO configSubGroup = matchKeywordBy(equals, configurationSubGroups, keyword);
|
||||
if (configSubGroup == null) {
|
||||
BiPredicate<String, String> startsWith = (a, b) -> { return a.startsWith(b); };
|
||||
configSubGroup = matchKeywordBy(startsWith, configurationSubGroups, keyword.toLowerCase());
|
||||
}
|
||||
return configSubGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationSubGroupVO findByNameAndGroup(String name, Long groupId) {
|
||||
SearchCriteria<ConfigurationSubGroupVO> sc = nameAndGroupSearch.create();
|
||||
sc.setParameters("name", name);
|
||||
sc.setParameters("groupId", groupId);
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConfigurationSubGroupVO> findByGroup(Long groupId) {
|
||||
SearchCriteria<ConfigurationSubGroupVO> sc = groupSearch.create();
|
||||
sc.setParameters("groupId", groupId);
|
||||
final Filter filter = new Filter(ConfigurationSubGroupVO.class, "precedence", true, null, null);
|
||||
return listIncludingRemovedBy(sc, filter);
|
||||
}
|
||||
}
|
||||
@ -33,10 +33,14 @@ import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
/**
|
||||
@ -70,6 +74,10 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
|
||||
private final static Logger s_logger = Logger.getLogger(ConfigDepotImpl.class);
|
||||
@Inject
|
||||
ConfigurationDao _configDao;
|
||||
@Inject
|
||||
ConfigurationGroupDao _configGroupDao;
|
||||
@Inject
|
||||
ConfigurationSubGroupDao _configSubGroupDao;
|
||||
List<Configurable> _configurables;
|
||||
List<ScopedConfigStorage> _scopedStorages;
|
||||
Set<Configurable> _configured = Collections.synchronizedSet(new HashSet<Configurable>());
|
||||
@ -139,6 +147,28 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
|
||||
}
|
||||
|
||||
private void createOrupdateConfigObject(Date date, String componentName, ConfigKey<?> key, String value) {
|
||||
Long groupId = 1L;
|
||||
Long subGroupId = 1L;
|
||||
if (key.group() != null) {
|
||||
Ternary<String, String, Long> group = key.group();
|
||||
ConfigurationGroupVO groupVO = _configGroupDao.findByName(group.first());
|
||||
if (groupVO == null) {
|
||||
groupVO = new ConfigurationGroupVO(group.first(), group.second(), group.third());
|
||||
groupVO = _configGroupDao.persist(groupVO);
|
||||
}
|
||||
groupId = groupVO.getId();
|
||||
}
|
||||
|
||||
if (key.subGroup() != null) {
|
||||
Pair<String, Long> subGroup = key.subGroup();
|
||||
ConfigurationSubGroupVO subGroupVO = _configSubGroupDao.findByNameAndGroup(subGroup.first(), groupId);
|
||||
if (subGroupVO == null) {
|
||||
subGroupVO = new ConfigurationSubGroupVO();
|
||||
subGroupVO = _configSubGroupDao.persist(subGroupVO);
|
||||
}
|
||||
subGroupId = subGroupVO.getId();
|
||||
}
|
||||
|
||||
ConfigurationVO vo = _configDao.findById(key.key());
|
||||
if (vo == null) {
|
||||
vo = new ConfigurationVO(componentName, key);
|
||||
@ -146,8 +176,25 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
|
||||
if (value != null) {
|
||||
vo.setValue(value);
|
||||
}
|
||||
|
||||
if (key.group() == null && key.subGroup() == null ) {
|
||||
Pair<Long, Long> configGroupAndSubGroup = getConfigurationGroupAndSubGroupByName(key.key());
|
||||
vo.setGroupId(configGroupAndSubGroup.first());
|
||||
vo.setSubGroupId(configGroupAndSubGroup.second());
|
||||
} else {
|
||||
vo.setGroupId(groupId);
|
||||
vo.setSubGroupId(subGroupId);
|
||||
}
|
||||
if (key.kind() != null) {
|
||||
vo.setKind(key.kind().toString());
|
||||
}
|
||||
if (key.options() != null) {
|
||||
vo.setOptions(key.options());
|
||||
}
|
||||
|
||||
_configDao.persist(vo);
|
||||
} else {
|
||||
boolean configUpdated = false;
|
||||
if (vo.isDynamic() != key.isDynamic() || !ObjectUtils.equals(vo.getDescription(), key.description()) || !ObjectUtils.equals(vo.getDefaultValue(), key.defaultValue()) ||
|
||||
!ObjectUtils.equals(vo.getScope(), key.scope().toString()) ||
|
||||
!ObjectUtils.equals(vo.getComponent(), componentName)) {
|
||||
@ -157,6 +204,48 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
|
||||
vo.setScope(key.scope().toString());
|
||||
vo.setComponent(componentName);
|
||||
vo.setUpdated(date);
|
||||
configUpdated = true;
|
||||
}
|
||||
|
||||
if (key.displayText() != null && !ObjectUtils.equals(vo.getDisplayText(), key.displayText())) {
|
||||
vo.setDisplayText(key.displayText());
|
||||
configUpdated = true;
|
||||
}
|
||||
|
||||
if (key.parent() != null && !ObjectUtils.equals(vo.getParent(), key.parent())) {
|
||||
vo.setParent(key.parent());
|
||||
configUpdated = true;
|
||||
}
|
||||
|
||||
if (key.group() == null && key.subGroup() == null ) {
|
||||
Pair<Long, Long> configGroupAndSubGroup = getConfigurationGroupAndSubGroupByName(key.key());
|
||||
if (configGroupAndSubGroup.first() != 1 && configGroupAndSubGroup.second() != 1) {
|
||||
vo.setGroupId(configGroupAndSubGroup.first());
|
||||
vo.setSubGroupId(configGroupAndSubGroup.second());
|
||||
configUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (key.group() != null && !ObjectUtils.equals(vo.getGroupId(), groupId)) {
|
||||
vo.setGroupId(groupId);
|
||||
configUpdated = true;
|
||||
}
|
||||
|
||||
if (key.subGroup() != null && !ObjectUtils.equals(vo.getSubGroupId(), subGroupId)) {
|
||||
vo.setSubGroupId(subGroupId);
|
||||
configUpdated = true;
|
||||
}
|
||||
|
||||
if (key.kind() != null) {
|
||||
vo.setKind(key.kind().toString());
|
||||
configUpdated = true;
|
||||
}
|
||||
if (key.options() != null) {
|
||||
vo.setOptions(key.options());
|
||||
configUpdated = true;
|
||||
}
|
||||
|
||||
if (configUpdated) {
|
||||
_configDao.persist(vo);
|
||||
}
|
||||
}
|
||||
@ -227,6 +316,31 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
|
||||
@Override
|
||||
public <T> void createOrUpdateConfigObject(String componentName, ConfigKey<T> key, String value) {
|
||||
createOrupdateConfigObject(new Date(), componentName, key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Long, Long> getConfigurationGroupAndSubGroupByName(String configName) {
|
||||
Long subGroupId = 1L;
|
||||
Long groupId = 1L;
|
||||
if (StringUtils.isNotBlank(configName)) {
|
||||
String[] nameWords = configName.split("\\.");
|
||||
if (nameWords.length > 0) {
|
||||
for (int index = 0; index < nameWords.length; index++) {
|
||||
ConfigurationSubGroupVO configSubGroup = _configSubGroupDao.findByName(nameWords[index]);
|
||||
|
||||
if (configSubGroup == null) {
|
||||
configSubGroup = _configSubGroupDao.findByKeyword(nameWords[index]);
|
||||
}
|
||||
|
||||
if (configSubGroup != null) {
|
||||
subGroupId = configSubGroup.getId();
|
||||
groupId = configSubGroup.getGroupId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Pair<>(groupId, subGroupId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,91 @@
|
||||
// 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.impl;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.config.ConfigurationGroup;
|
||||
|
||||
@Entity
|
||||
@Table(name = "configuration_group")
|
||||
public class ConfigurationGroupVO implements ConfigurationGroup {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id = 1;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "description", length = 1024)
|
||||
private String description = null;
|
||||
|
||||
@Column(name = "precedence")
|
||||
private Long precedence = 999L;
|
||||
|
||||
protected ConfigurationGroupVO() {
|
||||
}
|
||||
|
||||
public ConfigurationGroupVO(String name, String description) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.precedence = 999L;
|
||||
}
|
||||
|
||||
public ConfigurationGroupVO(String name, String description, Long precedence) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.precedence = precedence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getPrecedence() {
|
||||
return precedence;
|
||||
}
|
||||
|
||||
public void setPrecedence(Long precedence) {
|
||||
this.precedence = precedence;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
// 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.impl;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.config.ConfigurationSubGroup;
|
||||
|
||||
@Entity
|
||||
@Table(name = "configuration_subgroup")
|
||||
public class ConfigurationSubGroupVO implements ConfigurationSubGroup {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id = 1;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "keywords")
|
||||
private String keywords = null;
|
||||
|
||||
@Column(name = "precedence")
|
||||
private Long precedence = 999L;
|
||||
|
||||
@Column(name = "group_id")
|
||||
private Long groupId;
|
||||
|
||||
protected ConfigurationSubGroupVO() {
|
||||
}
|
||||
|
||||
public ConfigurationSubGroupVO(String name, String keywords) {
|
||||
this.name = name;
|
||||
this.keywords = keywords;
|
||||
this.precedence = 999L;
|
||||
}
|
||||
|
||||
public ConfigurationSubGroupVO(String name, String keywords, Long precedence) {
|
||||
this.name = name;
|
||||
this.keywords = keywords;
|
||||
this.precedence = precedence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeywords() {
|
||||
return keywords;
|
||||
}
|
||||
|
||||
public void setKeywords(String keywords) {
|
||||
this.keywords = keywords;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getPrecedence() {
|
||||
return precedence;
|
||||
}
|
||||
|
||||
public void setPrecedence(Long precedence) {
|
||||
this.precedence = precedence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(Long groupId) {
|
||||
this.groupId = groupId;
|
||||
}
|
||||
}
|
||||
@ -27,6 +27,7 @@ import javax.persistence.TemporalType;
|
||||
|
||||
import org.apache.cloudstack.config.Configuration;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||
|
||||
@ -65,20 +66,50 @@ public class ConfigurationVO implements Configuration {
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date updated;
|
||||
|
||||
@Column(name = "group_id")
|
||||
private Long groupId = 1L;
|
||||
|
||||
@Column(name = "subgroup_id")
|
||||
private Long subGroupId = 1L;
|
||||
|
||||
@Column(name = "parent")
|
||||
private String parent;
|
||||
|
||||
@Column(name = "display_text", length = 255)
|
||||
private String displayText;
|
||||
|
||||
@Column(name = "kind")
|
||||
private String kind;
|
||||
|
||||
@Column(name = "options")
|
||||
private String options;
|
||||
|
||||
protected ConfigurationVO() {
|
||||
}
|
||||
|
||||
public ConfigurationVO(String category, String instance, String component, String name, String value, String description) {
|
||||
this(category, instance, component, name, value, description, null, null);
|
||||
}
|
||||
|
||||
public ConfigurationVO(String category, String instance, String component, String name, String value, String description, String displayText, String parentConfigName) {
|
||||
this(category, instance, component, name, value, description, displayText, parentConfigName, null, null);
|
||||
}
|
||||
|
||||
public ConfigurationVO(String category, String instance, String component, String name, String value, String description, String displayText, String parentConfigName, Long groupId, Long subGroupId) {
|
||||
this.category = category;
|
||||
this.instance = instance;
|
||||
this.component = component;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.parent = parentConfigName;
|
||||
setValue(value);
|
||||
setDisplayText(displayText);
|
||||
setGroupId(groupId);
|
||||
setSubGroupId(subGroupId);
|
||||
}
|
||||
|
||||
public ConfigurationVO(String component, ConfigKey<?> key) {
|
||||
this(key.category(), "DEFAULT", component, key.key(), key.defaultValue(), key.description());
|
||||
this(key.category(), "DEFAULT", component, key.key(), key.defaultValue(), key.description(), key.displayText(), key.parent());
|
||||
defaultValue = key.defaultValue();
|
||||
dynamic = key.isDynamic();
|
||||
scope = key.scope() != null ? key.scope().toString() : null;
|
||||
@ -186,4 +217,83 @@ public class ConfigurationVO implements Configuration {
|
||||
public void setUpdated(Date updated) {
|
||||
this.updated = updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(Long groupId) {
|
||||
if (groupId != null) {
|
||||
this.groupId = groupId;
|
||||
} else {
|
||||
this.groupId = 1L;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSubGroupId() {
|
||||
return subGroupId;
|
||||
}
|
||||
|
||||
public void setSubGroupId(Long subGroupId) {
|
||||
if (subGroupId != null) {
|
||||
this.subGroupId = subGroupId;
|
||||
} else {
|
||||
this.subGroupId = 1L;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(String parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayText() {
|
||||
if (StringUtils.isNotBlank(displayText)) {
|
||||
return displayText;
|
||||
}
|
||||
|
||||
String displayText = "";
|
||||
String name = getName();
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
name = name.replace(".", " ");
|
||||
displayText = name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
return displayText;
|
||||
}
|
||||
|
||||
public void setDisplayText(String displayText) {
|
||||
if (StringUtils.isBlank(displayText)) {
|
||||
String name = getName();
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
name = name.replace(".", " ");
|
||||
displayText = name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
this.displayText = displayText;
|
||||
}
|
||||
|
||||
public String getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
public void setKind(String kind) {
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
public String getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOptions(String options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -45,6 +45,12 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="configurationGroupDaoImpl"
|
||||
class="org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl" />
|
||||
|
||||
<bean id="configurationSubGroupDaoImpl"
|
||||
class="org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl" />
|
||||
|
||||
<bean id="scopedConfigStorageRegistry"
|
||||
class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry" />
|
||||
|
||||
|
||||
@ -39,12 +39,12 @@ public class ConfigKeyTest {
|
||||
@Test
|
||||
public void testIsSameKeyAs() {
|
||||
ConfigKey key = new ConfigKey("cat", String.class, "naam", "nick", "bijnaam", true, Scope.Cluster);
|
||||
Assert.assertTrue("1 and one should be considdered the same address", key.isSameKeyAs("naam"));
|
||||
Assert.assertTrue("1 and one should be considered the same address", key.isSameKeyAs("naam"));
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void testIsSameKeyAsThrowingCloudRuntimeException() {
|
||||
ConfigKey key = new ConfigKey("hond", Boolean.class, "naam", "truus", "thrown name", false);
|
||||
Assert.assertFalse("zero and 0L should be considdered the same address", key.isSameKeyAs(0L));
|
||||
Assert.assertFalse("zero and 0L should be considered the same address", key.isSameKeyAs(0L));
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
// under the License.
|
||||
package org.apache.cloudstack.framework.config.impl;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@ -25,9 +26,13 @@ import java.util.ArrayList;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.apache.cloudstack.framework.config.ConfigDepot;
|
||||
@ -36,11 +41,15 @@ import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.db.EntityManager;
|
||||
|
||||
public class ConfigDepotAdminTest extends TestCase {
|
||||
private final static ConfigKey<Integer> DynamicIntCK = new ConfigKey<Integer>(Integer.class, "dynIntKey", "Advance", "10", "Test Key", true);
|
||||
private final static ConfigKey<Integer> StaticIntCK = new ConfigKey<Integer>(Integer.class, "statIntKey", "Advance", "10", "Test Key", false);
|
||||
private final static ConfigKey<Integer> TestCK = new ConfigKey<>(Integer.class, "testKey", "Advance", "30", "Test Key", false,
|
||||
ConfigKey.Scope.Global, null, "Test Display Text", null, new Ternary<>("TestGroup", "Test Group", 3L), new Pair<>("Test SubGroup", 1L));
|
||||
|
||||
@Mock
|
||||
Configurable _configurable;
|
||||
@ -56,6 +65,12 @@ public class ConfigDepotAdminTest extends TestCase {
|
||||
@Mock
|
||||
ConfigurationDao _configDao;
|
||||
|
||||
@Mock
|
||||
ConfigurationGroupDao _configGroupDao;
|
||||
|
||||
@Mock
|
||||
ConfigurationSubGroupDao _configSubGroupDao;
|
||||
|
||||
@Mock
|
||||
ScopedConfigStorage _scopedStorage;
|
||||
|
||||
@ -68,6 +83,8 @@ public class ConfigDepotAdminTest extends TestCase {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
_depotAdmin = new ConfigDepotImpl();
|
||||
_depotAdmin._configDao = _configDao;
|
||||
_depotAdmin._configGroupDao = _configGroupDao;
|
||||
_depotAdmin._configSubGroupDao = _configSubGroupDao;
|
||||
_depotAdmin._configurables = new ArrayList<Configurable>();
|
||||
_depotAdmin._configurables.add(_configurable);
|
||||
_depotAdmin._scopedStorages = new ArrayList<ScopedConfigStorage>();
|
||||
@ -80,22 +97,58 @@ public class ConfigDepotAdminTest extends TestCase {
|
||||
dynamicIntCV.setValue("100");
|
||||
ConfigurationVO staticIntCV = new ConfigurationVO("UnitTestComponent", StaticIntCK);
|
||||
dynamicIntCV.setValue("200");
|
||||
ConfigurationVO testCV = new ConfigurationVO("UnitTestComponent", TestCK);
|
||||
|
||||
when(_configurable.getConfigComponentName()).thenReturn("UnitTestComponent");
|
||||
when(_configurable.getConfigKeys()).thenReturn(new ConfigKey<?>[] {DynamicIntCK, StaticIntCK});
|
||||
when(_configurable.getConfigKeys()).thenReturn(new ConfigKey<?>[] {DynamicIntCK, StaticIntCK, TestCK});
|
||||
when(_configDao.findById(StaticIntCK.key())).thenReturn(null);
|
||||
when(_configDao.findById(DynamicIntCK.key())).thenReturn(dynamicIntCV);
|
||||
when(_configDao.findById(TestCK.key())).thenReturn(testCV);
|
||||
when(_configDao.persist(any(ConfigurationVO.class))).thenReturn(dynamicIntCV);
|
||||
|
||||
_depotAdmin.populateConfigurations();
|
||||
|
||||
// This is once because DynamicIntCK is returned.
|
||||
verify(_configDao, times(1)).persist(any(ConfigurationVO.class));
|
||||
|
||||
when(_configDao.findById(DynamicIntCK.key())).thenReturn(dynamicIntCV);
|
||||
when(_configDao.findById(TestCK.key())).thenReturn(null);
|
||||
_depotAdmin._configured.clear();
|
||||
_depotAdmin.populateConfigurations();
|
||||
// This is two because DynamicIntCK also returns null.
|
||||
verify(_configDao, times(2)).persist(any(ConfigurationVO.class));
|
||||
// This is three because DynamicIntCK, TestCK also returns null.
|
||||
verify(_configDao, times(3)).persist(any(ConfigurationVO.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultConfigurationGroupAndSubGroup() {
|
||||
Mockito.when(_configSubGroupDao.findByName(anyString())).thenReturn(null);
|
||||
Mockito.when(_configSubGroupDao.findByKeyword(anyString())).thenReturn(null);
|
||||
|
||||
Pair<Long, Long> configGroupAndSubGroup = _depotAdmin.getConfigurationGroupAndSubGroupByName("test.storage.config.setting");
|
||||
|
||||
Assert.assertEquals(1L, configGroupAndSubGroup.first().longValue());
|
||||
Assert.assertEquals(1L, configGroupAndSubGroup.second().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigurationGroupAndSubGroup() {
|
||||
ConfigurationGroupVO testGroup = new ConfigurationGroupVO("TestGroup", "Test Group", 3L);
|
||||
ConfigurationSubGroupVO testSubGroup = new ConfigurationSubGroupVO("TestSubGroup", null, 1L);
|
||||
testSubGroup.setGroupId(9L);
|
||||
Mockito.when(_configSubGroupDao.findByName("storage")).thenReturn(testSubGroup);
|
||||
Mockito.when(_configSubGroupDao.findByKeyword(anyString())).thenReturn(null);
|
||||
|
||||
Pair<Long, Long> configGroupAndSubGroup = _depotAdmin.getConfigurationGroupAndSubGroupByName("test.storage.config.setting");
|
||||
|
||||
Assert.assertEquals(9L, configGroupAndSubGroup.first().longValue());
|
||||
Assert.assertEquals(1L, configGroupAndSubGroup.second().longValue());
|
||||
|
||||
testSubGroup.setGroupId(5L);
|
||||
Mockito.when(_configSubGroupDao.findByName(anyString())).thenReturn(null);
|
||||
Mockito.when(_configSubGroupDao.findByKeyword("storage")).thenReturn(testSubGroup);
|
||||
|
||||
configGroupAndSubGroup = _depotAdmin.getConfigurationGroupAndSubGroupByName("test.storage.config.setting");
|
||||
|
||||
Assert.assertEquals(5L, configGroupAndSubGroup.first().longValue());
|
||||
Assert.assertEquals(1L, configGroupAndSubGroup.second().longValue());
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,14 +18,17 @@
|
||||
*/
|
||||
package org.apache.cloudstack.framework.jobs;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import org.apache.cloudstack.framework.config.ConfigDepot;
|
||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.cloud.storage.dao.StoragePoolDetailsDaoImpl;
|
||||
|
||||
@ -42,6 +45,16 @@ public class AsyncJobManagerTestConfiguration {
|
||||
return new ConfigurationDaoImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurationGroupDao configGroupDao() {
|
||||
return new ConfigurationGroupDaoImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurationSubGroupDao configSubGroupDao() {
|
||||
return new ConfigurationSubGroupDaoImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ScopedConfigStorage scopedConfigStorage() {
|
||||
return new StoragePoolDetailsDaoImpl();
|
||||
|
||||
@ -136,14 +136,14 @@ public class ExtensionRegistry implements Registry<Object>, Configurable, BeanNa
|
||||
List<ConfigKey<String>> result = new ArrayList<ConfigKey<String>>();
|
||||
|
||||
if (orderConfigKey != null && orderConfigKeyObj == null) {
|
||||
orderConfigKeyObj = new ConfigKey<String>("Advanced", String.class, orderConfigKey, orderConfigDefault, "The order of precedence for the extensions", false);
|
||||
orderConfigKeyObj = new ConfigKey<>(String.class, orderConfigKey, "Advanced", orderConfigDefault, "The order of precedence for the extensions", false, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.Order, orderConfigDefault);
|
||||
}
|
||||
|
||||
if (orderConfigKeyObj != null)
|
||||
result.add(orderConfigKeyObj);
|
||||
|
||||
if (excludeKey != null && excludeKeyObj == null) {
|
||||
excludeKeyObj = new ConfigKey<String>("Advanced", String.class, excludeKey, excludeDefault, "Extensions to exclude from being registered", false);
|
||||
excludeKeyObj = new ConfigKey<>(String.class, excludeKey, "Advanced", excludeDefault, "Extensions to exclude from being registered", false, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
|
||||
}
|
||||
|
||||
if (excludeKeyObj != null) {
|
||||
|
||||
@ -45,33 +45,39 @@ public interface KubernetesClusterService extends PluggableService, Configurable
|
||||
"cloud.kubernetes.cluster.network.offering",
|
||||
"DefaultNetworkOfferingforKubernetesService",
|
||||
"Name of the network offering that will be used to create isolated network in which Kubernetes cluster VMs will be launched",
|
||||
false);
|
||||
false,
|
||||
KubernetesServiceEnabled.key());
|
||||
static final ConfigKey<Long> KubernetesClusterStartTimeout = new ConfigKey<Long>("Advanced", Long.class,
|
||||
"cloud.kubernetes.cluster.start.timeout",
|
||||
"3600",
|
||||
"Timeout interval (in seconds) in which start operation for a Kubernetes cluster should be completed",
|
||||
true);
|
||||
true,
|
||||
KubernetesServiceEnabled.key());
|
||||
static final ConfigKey<Long> KubernetesClusterScaleTimeout = new ConfigKey<Long>("Advanced", Long.class,
|
||||
"cloud.kubernetes.cluster.scale.timeout",
|
||||
"3600",
|
||||
"Timeout interval (in seconds) in which scale operation for a Kubernetes cluster should be completed",
|
||||
true);
|
||||
true,
|
||||
KubernetesServiceEnabled.key());
|
||||
static final ConfigKey<Long> KubernetesClusterUpgradeTimeout = new ConfigKey<Long>("Advanced", Long.class,
|
||||
"cloud.kubernetes.cluster.upgrade.timeout",
|
||||
"3600",
|
||||
"Timeout interval (in seconds) in which upgrade operation for a Kubernetes cluster should be completed. Not strictly obeyed while upgrade is in progress on a node",
|
||||
true);
|
||||
true,
|
||||
KubernetesServiceEnabled.key());
|
||||
static final ConfigKey<Boolean> KubernetesClusterExperimentalFeaturesEnabled = new ConfigKey<Boolean>("Advanced", Boolean.class,
|
||||
"cloud.kubernetes.cluster.experimental.features.enabled",
|
||||
"false",
|
||||
"Indicates whether experimental feature for Kubernetes cluster such as Docker private registry are enabled or not",
|
||||
true);
|
||||
true,
|
||||
KubernetesServiceEnabled.key());
|
||||
static final ConfigKey<Integer> KubernetesMaxClusterSize = new ConfigKey<Integer>("Advanced", Integer.class,
|
||||
"cloud.kubernetes.cluster.max.size",
|
||||
"10",
|
||||
"Maximum size of the kubernetes cluster.",
|
||||
true, ConfigKey.Scope.Account);
|
||||
|
||||
true,
|
||||
ConfigKey.Scope.Account,
|
||||
KubernetesServiceEnabled.key());
|
||||
|
||||
KubernetesCluster findById(final Long id);
|
||||
|
||||
|
||||
@ -26,10 +26,10 @@ public interface PrometheusExporterServer extends Manager {
|
||||
"Enable the prometheus exporter plugin, management server restart needed.", false);
|
||||
|
||||
ConfigKey<Integer> PrometheusExporterServerPort = new ConfigKey<>("Advanced", Integer.class, "prometheus.exporter.port", "9595",
|
||||
"The prometheus exporter server port", true);
|
||||
"The prometheus exporter server port", true, EnablePrometheusExporter.key());
|
||||
|
||||
ConfigKey<String> PrometheusExporterAllowedAddresses = new ConfigKey<>("Advanced", String.class, "prometheus.exporter.allowed.ips", "127.0.0.1",
|
||||
"List of comma separated prometheus server ips (with no spaces) that should be allowed to access the URLs", true);
|
||||
"List of comma separated prometheus server ips (with no spaces) that should be allowed to access the URLs", true, EnablePrometheusExporter.key());
|
||||
|
||||
ConfigKey<Integer> PrometheusExporterOfferingCountLimit = new ConfigKey<>("Advanced", Integer.class, "prometheus.exporter.offering.output.limit", "-1",
|
||||
"Limit the number of output for cloudstack_vms_total_by_size to the provided value. -1 for unlimited output.", true);
|
||||
|
||||
@ -21,6 +21,8 @@ import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl;
|
||||
import org.eclipse.jetty.security.IdentityService;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mockito;
|
||||
@ -304,14 +306,14 @@ import com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl;
|
||||
ApiDBUtils.class, ApplicationLoadBalancerRuleDaoImpl.class, AsyncJobDaoImpl.class, AsyncJobJoinDaoImpl.class, AsyncJobJoinMapDaoImpl.class,
|
||||
AsyncJobJournalDaoImpl.class, AsyncJobManagerImpl.class, AutoScalePolicyConditionMapDaoImpl.class, AutoScalePolicyDaoImpl.class, AutoScaleVmGroupDaoImpl.class,
|
||||
AutoScaleVmGroupPolicyMapDaoImpl.class, AutoScaleVmProfileDaoImpl.class, CapacityDaoImpl.class, ClusterDaoImpl.class, ClusterDetailsDaoImpl.class,
|
||||
ConditionDaoImpl.class, ConfigurationDaoImpl.class, ConfigurationManagerImpl.class, ConfigurationServerImpl.class, ConsoleProxyDaoImpl.class,
|
||||
ContrailElementImpl.class, ContrailGuru.class, ContrailManagerImpl.class, CounterDaoImpl.class, DataCenterDaoImpl.class, DataCenterDetailsDaoImpl.class, DataCenterIpAddressDaoImpl.class,
|
||||
DataCenterJoinDaoImpl.class, DataCenterLinkLocalIpAddressDaoImpl.class, DataCenterVnetDaoImpl.class, DcDetailsDaoImpl.class, DedicatedResourceDaoImpl.class,
|
||||
ConditionDaoImpl.class, ConfigurationDaoImpl.class, ConfigurationGroupDaoImpl.class, ConfigurationSubGroupDaoImpl.class, ConfigurationManagerImpl.class, ConfigurationServerImpl.class,
|
||||
ConsoleProxyDaoImpl.class, ContrailElementImpl.class, ContrailGuru.class, ContrailManagerImpl.class, CounterDaoImpl.class, DataCenterDaoImpl.class, DataCenterDetailsDaoImpl.class,
|
||||
DataCenterIpAddressDaoImpl.class, DataCenterJoinDaoImpl.class, DataCenterLinkLocalIpAddressDaoImpl.class, DataCenterVnetDaoImpl.class, DcDetailsDaoImpl.class, DedicatedResourceDaoImpl.class,
|
||||
DiskOfferingDaoImpl.class, DiskOfferingJoinDaoImpl.class, DomainDaoImpl.class, DomainDetailsDaoImpl.class, DomainManagerImpl.class, DomainRouterDaoImpl.class, DomainRouterJoinDaoImpl.class,
|
||||
EventDaoImpl.class, EventJoinDaoImpl.class, EventUtils.class, ExtensionRegistry.class, FirewallManagerImpl.class, FirewallRulesCidrsDaoImpl.class,
|
||||
FirewallRulesDaoImpl.class, GuestOSCategoryDaoImpl.class, GuestOSDaoImpl.class, HostDaoImpl.class, HostDetailsDaoImpl.class, HostJoinDaoImpl.class,
|
||||
HostPodDaoImpl.class, HostTagsDaoImpl.class, HostTransferMapDaoImpl.class, HypervisorCapabilitiesDaoImpl.class, HypervisorGuruManagerImpl.class,
|
||||
ImageStoreDaoImpl.class, ImageStoreJoinDaoImpl.class, InstanceGroupDaoImpl.class, InstanceGroupJoinDaoImpl.class,
|
||||
ImageStoreDaoImpl.class, ImageStoreJoinDaoImpl.class, InstanceGroupDaoImpl.class, InstanceGroupJoinDaoImpl.class,
|
||||
InstanceGroupVMMapDaoImpl.class, InternalLoadBalancerElement.class, IPAddressDaoImpl.class, IpAddressManagerImpl.class, Ipv6AddressManagerImpl.class, ItWorkDaoImpl.class, LBHealthCheckPolicyDaoImpl.class,
|
||||
LBStickinessPolicyDaoImpl.class, LaunchPermissionDaoImpl.class, LoadBalancerDaoImpl.class, LoadBalancerVMMapDaoImpl.class, LoadBalancingRulesManagerImpl.class,
|
||||
ManagementServerHostDaoImpl.class, MockAccountManager.class, NetworkACLDaoImpl.class, NetworkACLItemDaoImpl.class, NetworkACLManagerImpl.class,
|
||||
|
||||
@ -61,8 +61,8 @@ public interface SAML2AuthManager extends PluggableAPIAuthenticator, PluggableSe
|
||||
public static final ConfigKey<String> SAMLDefaultIdentityProviderId = new ConfigKey<String>("Advanced", String.class, "saml2.default.idpid", "https://openidp.feide.no",
|
||||
"The default IdP entity ID to use only in case of multiple IdPs", true);
|
||||
|
||||
public static final ConfigKey<String> SAMLSignatureAlgorithm = new ConfigKey<String>("Advanced", String.class, "saml2.sigalg", "SHA1",
|
||||
"The algorithm to use to when signing a SAML request. Default is SHA1, allowed algorithms: SHA1, SHA256, SHA384, SHA512", true);
|
||||
public static final ConfigKey<String> SAMLSignatureAlgorithm = new ConfigKey<>(String.class, "saml2.sigalg", "Advanced", "SHA1",
|
||||
"The algorithm to use to when signing a SAML request. Default is SHA1, allowed algorithms: SHA1, SHA256, SHA384, SHA512", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.Select, "SHA1,SHA256,SHA384,SHA512");
|
||||
|
||||
public static final ConfigKey<Boolean> SAMLAppendDomainSuffix = new ConfigKey<Boolean>("Advanced", Boolean.class, "saml2.append.idpdomain", "false",
|
||||
"If enabled, create account/user dialog with SAML SSO enabled will append the IdP domain to the user or account name in the UI dialog", true);
|
||||
|
||||
@ -22,6 +22,8 @@ under the License.
|
||||
<dao name="host pod dao" class="com.cloud.dc.dao.HostPodDaoImpl" />
|
||||
<dao name="Datacenter dao" class="com.cloud.dc.dao.DataCenterDaoImpl" />
|
||||
<dao name="Configuration dao" class="com.cloud.configuration.dao.ConfigurationDaoImpl" />
|
||||
<dao name="Configuration group dao" class="com.cloud.configuration.dao.ConfigurationGroupDaoImpl" />
|
||||
<dao name="Configuration subgroup dao" class="com.cloud.configuration.dao.ConfigurationSubGroupDaoImpl" />
|
||||
<dao name="Cluster dao" class="com.cloud.dc.dao.ClusterDaoImpl" />
|
||||
<dao name="Host dao" class="com.cloud.host.dao.HostDaoImpl" />
|
||||
<dao name="StoragePool dao" class="com.cloud.storage.dao.StoragePoolDaoImpl" />
|
||||
|
||||
@ -65,7 +65,9 @@ import org.apache.cloudstack.api.response.CapabilityResponse;
|
||||
import org.apache.cloudstack.api.response.CapacityResponse;
|
||||
import org.apache.cloudstack.api.response.ClusterResponse;
|
||||
import org.apache.cloudstack.api.response.ConditionResponse;
|
||||
import org.apache.cloudstack.api.response.ConfigurationGroupResponse;
|
||||
import org.apache.cloudstack.api.response.ConfigurationResponse;
|
||||
import org.apache.cloudstack.api.response.ConfigurationSubGroupResponse;
|
||||
import org.apache.cloudstack.api.response.ControlledEntityResponse;
|
||||
import org.apache.cloudstack.api.response.ControlledViewEntityResponse;
|
||||
import org.apache.cloudstack.api.response.CounterResponse;
|
||||
@ -170,6 +172,8 @@ import org.apache.cloudstack.backup.BackupOffering;
|
||||
import org.apache.cloudstack.backup.BackupSchedule;
|
||||
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
|
||||
import org.apache.cloudstack.config.Configuration;
|
||||
import org.apache.cloudstack.config.ConfigurationGroup;
|
||||
import org.apache.cloudstack.config.ConfigurationSubGroup;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.direct.download.DirectDownloadCertificate;
|
||||
import org.apache.cloudstack.direct.download.DirectDownloadCertificateHostMap;
|
||||
@ -560,6 +564,9 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
public ConfigurationResponse createConfigurationResponse(Configuration cfg) {
|
||||
ConfigurationResponse cfgResponse = new ConfigurationResponse();
|
||||
cfgResponse.setCategory(cfg.getCategory());
|
||||
Pair<String, String> configGroupAndSubGroup = _configMgr.getConfigurationGroupAndSubGroup(cfg.getName());
|
||||
cfgResponse.setGroup(configGroupAndSubGroup.first());
|
||||
cfgResponse.setSubGroup(configGroupAndSubGroup.second());
|
||||
cfgResponse.setDescription(cfg.getDescription());
|
||||
cfgResponse.setName(cfg.getName());
|
||||
if (cfg.isEncrypted()) {
|
||||
@ -567,12 +574,48 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
} else {
|
||||
cfgResponse.setValue(cfg.getValue());
|
||||
}
|
||||
cfgResponse.setDefaultValue(cfg.getDefaultValue());
|
||||
cfgResponse.setIsDynamic(cfg.isDynamic());
|
||||
cfgResponse.setComponent(cfg.getComponent());
|
||||
if (cfg.getParent() != null) {
|
||||
cfgResponse.setParent(cfg.getParent());
|
||||
}
|
||||
cfgResponse.setDisplayText(cfg.getDisplayText());
|
||||
cfgResponse.setType(_configMgr.getConfigurationType(cfg.getName()));
|
||||
if (cfg.getOptions() != null) {
|
||||
cfgResponse.setOptions(cfg.getOptions());
|
||||
}
|
||||
cfgResponse.setObjectName("configuration");
|
||||
|
||||
return cfgResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationGroupResponse createConfigurationGroupResponse(ConfigurationGroup cfgGroup) {
|
||||
ConfigurationGroupResponse cfgGroupResponse = new ConfigurationGroupResponse();
|
||||
cfgGroupResponse.setGroupName(cfgGroup.getName());
|
||||
cfgGroupResponse.setDescription(cfgGroup.getDescription());
|
||||
cfgGroupResponse.setPrecedence(cfgGroup.getPrecedence());
|
||||
|
||||
List<? extends ConfigurationSubGroup> subgroups = _configMgr.getConfigurationSubGroups(cfgGroup.getId());
|
||||
List<ConfigurationSubGroupResponse> cfgSubGroupResponses = new ArrayList<>();
|
||||
for (ConfigurationSubGroup subgroup : subgroups) {
|
||||
ConfigurationSubGroupResponse cfgSubGroupResponse = createConfigurationSubGroupResponse(subgroup);
|
||||
cfgSubGroupResponses.add(cfgSubGroupResponse);
|
||||
}
|
||||
cfgGroupResponse.setSubGroups(cfgSubGroupResponses);
|
||||
cfgGroupResponse.setObjectName("configurationgroup");
|
||||
return cfgGroupResponse;
|
||||
}
|
||||
|
||||
private ConfigurationSubGroupResponse createConfigurationSubGroupResponse(ConfigurationSubGroup cfgSubGroup) {
|
||||
ConfigurationSubGroupResponse cfgSubGroupResponse = new ConfigurationSubGroupResponse();
|
||||
cfgSubGroupResponse.setSubGroupName(cfgSubGroup.getName());
|
||||
cfgSubGroupResponse.setPrecedence(cfgSubGroup.getPrecedence());
|
||||
cfgSubGroupResponse.setObjectName("subgroup");
|
||||
return cfgSubGroupResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotResponse createSnapshotResponse(Snapshot snapshot) {
|
||||
SnapshotResponse snapshotResponse = new SnapshotResponse();
|
||||
|
||||
@ -54,6 +54,8 @@ public enum Config {
|
||||
"alert.email.addresses",
|
||||
null,
|
||||
"Comma separated list of email addresses which are going to receive alert emails.",
|
||||
null,
|
||||
ConfigKey.Kind.CSV,
|
||||
null),
|
||||
AlertEmailSender("Alert", ManagementServer.class, String.class, "alert.email.sender", null, "Sender of alert email (will be in the From header of the email).", null),
|
||||
AlertSMTPHost("Alert", ManagementServer.class, String.class, "alert.smtp.host", null, "SMTP hostname used for sending out email alerts.", null),
|
||||
@ -229,7 +231,9 @@ public enum Config {
|
||||
"network.loadbalancer.haproxy.stats.visibility",
|
||||
"global",
|
||||
"Load Balancer(haproxy) stats visibility, the value can be one of the following six parameters : global,guest-network,link-local,disabled,all,default",
|
||||
null),
|
||||
null,
|
||||
ConfigKey.Kind.Select,
|
||||
"global,guest-network,link-local,disabled,all,default"),
|
||||
NetworkLBHaproxyStatsUri(
|
||||
"Network",
|
||||
ManagementServer.class,
|
||||
@ -354,6 +358,8 @@ public enum Config {
|
||||
"network.dhcp.nondefaultnetwork.setgateway.guestos",
|
||||
"Windows",
|
||||
"The guest OS's name start with this fields would result in DHCP server response gateway information even when the network it's on is not default network. Names are separated by comma.",
|
||||
null,
|
||||
ConfigKey.Kind.CSV,
|
||||
null),
|
||||
|
||||
//VPN
|
||||
@ -425,8 +431,22 @@ public enum Config {
|
||||
"8001",
|
||||
"Console proxy command port that is used to communicate with management server",
|
||||
null),
|
||||
ConsoleProxyRestart("Console Proxy", AgentManager.class, Boolean.class, "consoleproxy.restart", "true", "Console proxy restart flag, defaulted to true", null),
|
||||
ConsoleProxyUrlDomain("Console Proxy", AgentManager.class, String.class, "consoleproxy.url.domain", "", "Console proxy url domain", "domainName", "privateip"),
|
||||
ConsoleProxyRestart(
|
||||
"Console Proxy",
|
||||
AgentManager.class,
|
||||
Boolean.class,
|
||||
"consoleproxy.restart",
|
||||
"true",
|
||||
"Console proxy restart flag, defaulted to true",
|
||||
null),
|
||||
ConsoleProxyUrlDomain(
|
||||
"Console Proxy",
|
||||
AgentManager.class,
|
||||
String.class,
|
||||
"consoleproxy.url.domain",
|
||||
"",
|
||||
"Console proxy url domain",
|
||||
"domainName,privateip"),
|
||||
ConsoleProxySessionMax(
|
||||
"Console Proxy",
|
||||
AgentManager.class,
|
||||
@ -649,7 +669,9 @@ public enum Config {
|
||||
HypervisorType.Hyperv + "," + HypervisorType.KVM + "," + HypervisorType.XenServer + "," + HypervisorType.VMware + "," + HypervisorType.BareMetal + "," +
|
||||
HypervisorType.Ovm + "," + HypervisorType.LXC + "," + HypervisorType.Ovm3,
|
||||
"The list of hypervisors that this deployment will use.",
|
||||
"hypervisorList"),
|
||||
"hypervisorList",
|
||||
ConfigKey.Kind.CSV,
|
||||
null),
|
||||
ManagementNetwork("Advanced", ManagementServer.class, String.class, "management.network.cidr", null, "The cidr of management server network", null),
|
||||
EventPurgeDelay(
|
||||
"Advanced",
|
||||
@ -903,7 +925,9 @@ public enum Config {
|
||||
"vm.allocation.algorithm",
|
||||
"random",
|
||||
"'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit', 'firstfitleastconsumed' : Order in which hosts within a cluster will be considered for VM/volume allocation.",
|
||||
null),
|
||||
null,
|
||||
ConfigKey.Kind.Select,
|
||||
"random,firstfit,userdispersing,userconcentratedpod_random,userconcentratedpod_firstfit,firstfitleastconsumed"),
|
||||
VmDeploymentPlanner(
|
||||
"Advanced",
|
||||
ManagementServer.class,
|
||||
@ -911,7 +935,9 @@ public enum Config {
|
||||
"vm.deployment.planner",
|
||||
"FirstFitPlanner",
|
||||
"'FirstFitPlanner', 'UserDispersingPlanner', 'UserConcentratedPodPlanner': DeploymentPlanner heuristic that will be used for VM deployment.",
|
||||
null),
|
||||
null,
|
||||
ConfigKey.Kind.Select,
|
||||
"FirstFitPlanner,UserDispersingPlanner,UserConcentratedPodPlanner"),
|
||||
ElasticLoadBalancerEnabled(
|
||||
"Advanced",
|
||||
ManagementServer.class,
|
||||
@ -1061,6 +1087,8 @@ public enum Config {
|
||||
"xenserver.pvdriver.version",
|
||||
"xenserver61",
|
||||
"default Xen PV driver version for registered template, valid value:xenserver56,xenserver61 ",
|
||||
"xenserver56,xenserver61",
|
||||
ConfigKey.Kind.Select,
|
||||
"xenserver56,xenserver61"),
|
||||
XenServerHotFix("Advanced",
|
||||
ManagementServer.class,
|
||||
@ -1127,7 +1155,9 @@ public enum Config {
|
||||
"vmware.root.disk.controller",
|
||||
"ide",
|
||||
"Specify the default disk controller for root volumes, valid values are scsi, ide, osdefault. Please check documentation for more details on each of these values.",
|
||||
null),
|
||||
null,
|
||||
ConfigKey.Kind.Select,
|
||||
"scsi,ide,osdefault"),
|
||||
VmwareSystemVmNicDeviceType(
|
||||
"Advanced",
|
||||
ManagementServer.class,
|
||||
@ -1135,7 +1165,9 @@ public enum Config {
|
||||
"vmware.systemvm.nic.device.type",
|
||||
"E1000",
|
||||
"Specify the default network device type for system VMs, valid values are E1000, PCNet32, Vmxnet2, Vmxnet3",
|
||||
null),
|
||||
null,
|
||||
ConfigKey.Kind.Select,
|
||||
"E1000,PCNet32,Vmxnet2,Vmxnet3"),
|
||||
VmwareRecycleHungWorker(
|
||||
"Advanced",
|
||||
ManagementServer.class,
|
||||
@ -1217,7 +1249,7 @@ public enum Config {
|
||||
TrafficSentinelIncludeZones(
|
||||
"Usage",
|
||||
ManagementServer.class,
|
||||
Integer.class,
|
||||
String.class,
|
||||
"traffic.sentinel.include.zones",
|
||||
"EXTERNAL",
|
||||
"Traffic going into specified list of zones is metered. For metering all traffic leave this parameter empty",
|
||||
@ -1225,7 +1257,7 @@ public enum Config {
|
||||
TrafficSentinelExcludeZones(
|
||||
"Usage",
|
||||
ManagementServer.class,
|
||||
Integer.class,
|
||||
String.class,
|
||||
"traffic.sentinel.exclude.zones",
|
||||
"",
|
||||
"Traffic going into specified list of zones is not metered.",
|
||||
@ -1361,6 +1393,8 @@ public enum Config {
|
||||
"network.dns.basiczone.updates",
|
||||
"all",
|
||||
"This parameter can take 2 values: all (default) and pod. It defines if DHCP/DNS requests have to be send to all dhcp servers in cloudstack, or only to the one in the same pod",
|
||||
"all,pod",
|
||||
ConfigKey.Kind.Select,
|
||||
"all,pod"),
|
||||
|
||||
ClusterMessageTimeOutSeconds(
|
||||
@ -1783,8 +1817,10 @@ public enum Config {
|
||||
private final String _name;
|
||||
private final String _defaultValue;
|
||||
private final String _description;
|
||||
private final String[] _range;
|
||||
private final String _range;
|
||||
private final String _scope; // Parameter can be at different levels (Zone/cluster/pool/account), by default every parameter is at global
|
||||
private final ConfigKey.Kind _kind;
|
||||
private final String _options;
|
||||
|
||||
private static final HashMap<String, List<Config>> s_scopeLevelConfigsMap = new HashMap<String, List<Config>>();
|
||||
static {
|
||||
@ -1833,7 +1869,11 @@ public enum Config {
|
||||
}
|
||||
}
|
||||
|
||||
private Config(String category, Class<?> componentClass, Class<?> type, String name, String defaultValue, String description, String... range) {
|
||||
private Config(String category, Class<?> componentClass, Class<?> type, String name, String defaultValue, String description, String range) {
|
||||
this(category, componentClass, type, name, defaultValue, description, range, null, null);
|
||||
}
|
||||
|
||||
private Config(String category, Class<?> componentClass, Class<?> type, String name, String defaultValue, String description, String range, ConfigKey.Kind kind, String options) {
|
||||
_category = category;
|
||||
_componentClass = componentClass;
|
||||
_type = type;
|
||||
@ -1842,6 +1882,8 @@ public enum Config {
|
||||
_description = description;
|
||||
_range = range;
|
||||
_scope = ConfigKey.Scope.Global.toString();
|
||||
_kind = kind;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
@ -1868,6 +1910,17 @@ public enum Config {
|
||||
return _scope;
|
||||
}
|
||||
|
||||
public String getKind() {
|
||||
if (_kind == null) {
|
||||
return null;
|
||||
}
|
||||
return _kind.toString();
|
||||
}
|
||||
|
||||
public String getOptions() {
|
||||
return _options;
|
||||
}
|
||||
|
||||
public String getComponent() {
|
||||
if (_componentClass == ManagementServer.class) {
|
||||
return "management-server";
|
||||
@ -1896,7 +1949,7 @@ public enum Config {
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getRange() {
|
||||
public String getRange() {
|
||||
return _range;
|
||||
}
|
||||
|
||||
|
||||
@ -97,6 +97,10 @@ 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.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationGroupVO;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageSubscriber;
|
||||
@ -296,6 +300,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
@Inject
|
||||
ConfigurationDao _configDao;
|
||||
@Inject
|
||||
ConfigurationGroupDao _configGroupDao;
|
||||
@Inject
|
||||
ConfigurationSubGroupDao _configSubGroupDao;
|
||||
@Inject
|
||||
ConfigDepot _configDepot;
|
||||
@Inject
|
||||
HostPodDao _podDao;
|
||||
@ -1232,10 +1240,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
return null;
|
||||
}
|
||||
|
||||
final String[] range = configuration.getRange();
|
||||
if (range == null) {
|
||||
if (configuration.getRange() == null) {
|
||||
return null;
|
||||
}
|
||||
String[] range = configuration.getRange().split(",");
|
||||
|
||||
if (type.equals(String.class)) {
|
||||
return validateIfStringValueIsInRange(name, value, range);
|
||||
@ -7563,6 +7571,91 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigurationType(final String configName) {
|
||||
final ConfigurationVO cfg = _configDao.findByName(configName);
|
||||
if (cfg == null) {
|
||||
s_logger.warn("Configuration " + configName + " not found");
|
||||
return Configuration.ValueType.String.name();
|
||||
}
|
||||
|
||||
if (weightBasedParametersForValidation.contains(configName)) {
|
||||
return Configuration.ValueType.Range.name();
|
||||
}
|
||||
|
||||
Class<?> type = null;
|
||||
final Config c = Config.getConfig(configName);
|
||||
if (c == null) {
|
||||
s_logger.warn("Configuration " + configName + " no found. Perhaps moved to ConfigDepot");
|
||||
final ConfigKey<?> configKey = _configDepot.get(configName);
|
||||
if (configKey == null) {
|
||||
s_logger.warn("Couldn't find configuration " + configName + " in ConfigDepot too.");
|
||||
return Configuration.ValueType.String.name();
|
||||
}
|
||||
type = configKey.type();
|
||||
} else {
|
||||
type = c.getType();
|
||||
}
|
||||
|
||||
return getInputType(type, cfg);
|
||||
}
|
||||
|
||||
private String getInputType(Class<?> type, ConfigurationVO cfg) {
|
||||
if (type == null) {
|
||||
return Configuration.ValueType.String.name();
|
||||
}
|
||||
|
||||
if (type == String.class || type == Character.class) {
|
||||
if (cfg.getKind() == null) {
|
||||
return Configuration.ValueType.String.name();
|
||||
}
|
||||
return cfg.getKind();
|
||||
}
|
||||
if (type == Integer.class || type == Long.class || type == Short.class) {
|
||||
return Configuration.ValueType.Number.name();
|
||||
}
|
||||
if (type == Float.class || type == Double.class) {
|
||||
return Configuration.ValueType.Decimal.name();
|
||||
}
|
||||
if (type == Boolean.class) {
|
||||
return Configuration.ValueType.Boolean.name();
|
||||
}
|
||||
return Configuration.ValueType.String.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<String, String> getConfigurationGroupAndSubGroup(final String configName) {
|
||||
if (StringUtils.isBlank(configName)) {
|
||||
throw new CloudRuntimeException("Empty configuration name provided");
|
||||
}
|
||||
|
||||
final ConfigurationVO cfg = _configDao.findByName(configName);
|
||||
if (cfg == null) {
|
||||
s_logger.warn("Configuration " + configName + " not found");
|
||||
throw new InvalidParameterValueException("configuration with name " + configName + " doesn't exist");
|
||||
}
|
||||
|
||||
String groupName = "Miscellaneous";
|
||||
String subGroupName = "Others";
|
||||
ConfigurationSubGroupVO configSubGroup = _configSubGroupDao.findById(cfg.getSubGroupId());
|
||||
if (configSubGroup != null) {
|
||||
subGroupName = configSubGroup.getName();
|
||||
}
|
||||
|
||||
ConfigurationGroupVO configGroup = _configGroupDao.findById(cfg.getGroupId());
|
||||
if (configGroup != null) {
|
||||
groupName = configGroup.getName();
|
||||
}
|
||||
|
||||
return new Pair<String, String>(groupName, subGroupName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConfigurationSubGroupVO> getConfigurationSubGroups(final Long groupId) {
|
||||
List<ConfigurationSubGroupVO> configSubGroups = _configSubGroupDao.findByGroup(groupId);
|
||||
return configSubGroups;
|
||||
}
|
||||
|
||||
static class ParamCountPair {
|
||||
private Long id;
|
||||
private int paramCount;
|
||||
|
||||
@ -63,7 +63,7 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
|
||||
static final ConfigKey<String> RouterTemplateOvm3 = new ConfigKey<String>(String.class, RouterTemplateOvm3CK, "Advanced", "SystemVM Template (Ovm3)",
|
||||
"Name of the default router template on Ovm3.", true, ConfigKey.Scope.Zone, null);
|
||||
|
||||
static final ConfigKey<String> SetServiceMonitor = new ConfigKey<String>(String.class, SetServiceMonitorCK, "Advanced", "true",
|
||||
static final ConfigKey<Boolean> SetServiceMonitor = new ConfigKey<Boolean>(Boolean.class, SetServiceMonitorCK, "Advanced", "true",
|
||||
"service monitoring in router enable/disable option, default true", true, ConfigKey.Scope.Zone, null);
|
||||
|
||||
static final ConfigKey<Integer> RouterAlertsCheckInterval = new ConfigKey<Integer>(Integer.class, RouterAlertsCheckIntervalCK, "Advanced", "1800",
|
||||
@ -84,36 +84,36 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
|
||||
true, ConfigKey.Scope.Global, null);
|
||||
static final ConfigKey<Integer> RouterHealthChecksBasicInterval = new ConfigKey<Integer>(Integer.class, "router.health.checks.basic.interval", "Advanced", "3",
|
||||
"Interval in minutes at which basic router health checks are performed. If set to 0, no tests are scheduled.",
|
||||
true, ConfigKey.Scope.Global, null);
|
||||
true, ConfigKey.Scope.Global, null, RouterHealthChecksEnabled.key());
|
||||
static final ConfigKey<Integer> RouterHealthChecksAdvancedInterval = new ConfigKey<Integer>(Integer.class, "router.health.checks.advanced.interval", "Advanced", "10",
|
||||
"Interval in minutes at which advanced router health checks are performed. If set to 0, no tests are scheduled.",
|
||||
true, ConfigKey.Scope.Global, null);
|
||||
true, ConfigKey.Scope.Global, null, RouterHealthChecksEnabled.key());
|
||||
static final ConfigKey<Integer> RouterHealthChecksConfigRefreshInterval = new ConfigKey<Integer>(Integer.class, RouterHealthChecksConfigRefreshIntervalCK, "Advanced", "10",
|
||||
"Interval in minutes at which router health checks config - such as scheduling intervals, excluded checks, etc is updated on virtual routers by the management server. This value should" +
|
||||
" be sufficiently high (like 2x) from the router.health.checks.basic.interval and router.health.checks.advanced.interval so that there is time between new results generation and results generation for passed data.",
|
||||
false, ConfigKey.Scope.Global, null);
|
||||
false, ConfigKey.Scope.Global, null, RouterHealthChecksEnabled.key());
|
||||
static final ConfigKey<Integer> RouterHealthChecksResultFetchInterval = new ConfigKey<Integer>(Integer.class, RouterHealthChecksResultFetchIntervalCK, "Advanced", "10",
|
||||
"Interval in minutes at which router health checks results are fetched by management server. On each result fetch, management server evaluates need to recreate VR as per configuration of " + RouterHealthChecksFailuresToRecreateVrCK +
|
||||
"This value should be sufficiently high (like 2x) from the router.health.checks.basic.interval and router.health.checks.advanced.interval so that there is time between new results generation and fetch.",
|
||||
false, ConfigKey.Scope.Global, null);
|
||||
false, ConfigKey.Scope.Global, null, RouterHealthChecksEnabled.key());
|
||||
static final ConfigKey<String> RouterHealthChecksFailuresToRecreateVr = new ConfigKey<String>(String.class, RouterHealthChecksFailuresToRecreateVrCK, "Advanced", "",
|
||||
"Health checks failures defined by this config are the checks that should cause router recreation. If empty the recreate is not attempted for any health check failure. Possible values are comma separated script names " +
|
||||
"from systemvm’s /root/health_scripts/ (namely - cpu_usage_check.py, dhcp_check.py, disk_space_check.py, dns_check.py, gateways_check.py, haproxy_check.py, iptables_check.py, memory_usage_check.py, router_version_check.py), connectivity.test, filesystem.writable.test " +
|
||||
" or services (namely - loadbalancing.service, webserver.service, dhcp.service) ",
|
||||
true, ConfigKey.Scope.Zone, null);
|
||||
true, ConfigKey.Scope.Zone, null, null, RouterHealthChecksEnabled.key(), null, null, ConfigKey.Kind.CSV, null);
|
||||
static final ConfigKey<String> RouterHealthChecksToExclude = new ConfigKey<String>(String.class, "router.health.checks.to.exclude", "Advanced", "",
|
||||
"Health checks that should be excluded when executing scheduled checks on the router. This can be a comma separated list of script names placed in the '/root/health_checks/' folder. Currently the following scripts are " +
|
||||
"placed in default systemvm template - cpu_usage_check.py, disk_space_check.py, gateways_check.py, iptables_check.py, router_version_check.py, dhcp_check.py, dns_check.py, haproxy_check.py, memory_usage_check.py.",
|
||||
true, ConfigKey.Scope.Zone, null);
|
||||
true, ConfigKey.Scope.Zone, null, null, RouterHealthChecksEnabled.key(), null, null, ConfigKey.Kind.CSV, null);
|
||||
static final ConfigKey<Double> RouterHealthChecksFreeDiskSpaceThreshold = new ConfigKey<Double>(Double.class, "router.health.checks.free.disk.space.threshold",
|
||||
"Advanced", "100", "Free disk space threshold (in MB) on VR below which the check is considered a failure.",
|
||||
true, ConfigKey.Scope.Zone, null);
|
||||
true, ConfigKey.Scope.Zone, null, RouterHealthChecksEnabled.key());
|
||||
static final ConfigKey<Double> RouterHealthChecksMaxCpuUsageThreshold = new ConfigKey<Double>(Double.class, "router.health.checks.max.cpu.usage.threshold",
|
||||
"Advanced", "100", " Max CPU Usage threshold as % above which check is considered a failure.",
|
||||
true, ConfigKey.Scope.Zone, null);
|
||||
true, ConfigKey.Scope.Zone, null, RouterHealthChecksEnabled.key());
|
||||
static final ConfigKey<Double> RouterHealthChecksMaxMemoryUsageThreshold = new ConfigKey<Double>(Double.class, "router.health.checks.max.memory.usage.threshold",
|
||||
"Advanced", "100", "Max Memory Usage threshold as % above which check is considered a failure.",
|
||||
true, ConfigKey.Scope.Zone, null);
|
||||
true, ConfigKey.Scope.Zone, null, RouterHealthChecksEnabled.key());
|
||||
ConfigKey<String> RouterLogrotateFrequency = new ConfigKey<>(String.class, "router.logrotate.frequency", "Advanced", "*:00:00",
|
||||
"Sets the frequency of the logrotate service on the virtual router. The default value is *:00:00 (hourly) and follows the last block of " +
|
||||
"OnCalendar standard [Hour:Minute:Second]. e.g, *:*:00 is for every minute and */12:00:00 is for every 12 hours. See Systemd Timers for more options. " +
|
||||
|
||||
@ -1862,10 +1862,10 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
|
||||
|
||||
s_logger.debug("Found " + routers.size() + " running routers. ");
|
||||
for (final DomainRouterVO router : routers) {
|
||||
final String serviceMonitoringFlag = SetServiceMonitor.valueIn(router.getDataCenterId());
|
||||
final Boolean serviceMonitoringFlag = SetServiceMonitor.valueIn(router.getDataCenterId());
|
||||
// Skip the routers in VPC network or skip the routers where
|
||||
// Monitor service is not enabled in the corresponding Zone
|
||||
if (!Boolean.parseBoolean(serviceMonitoringFlag)) {
|
||||
if (serviceMonitoringFlag == null || !serviceMonitoringFlag) {
|
||||
continue;
|
||||
}
|
||||
String controlIP = _routerControlHelper.getRouterControlIp(router.getId());
|
||||
|
||||
@ -98,6 +98,7 @@ import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.PasswordGenerator;
|
||||
import com.cloud.utils.PropertiesUtil;
|
||||
import com.cloud.utils.component.ComponentLifecycle;
|
||||
@ -202,6 +203,16 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
|
||||
String description = c.getDescription();
|
||||
ConfigurationVO configVO = new ConfigurationVO(category, instance, component, name, value, description);
|
||||
configVO.setDefaultValue(value);
|
||||
Pair<Long, Long> configGroupAndSubGroup = _configDepotAdmin.getConfigurationGroupAndSubGroupByName(name);
|
||||
configVO.setGroupId(configGroupAndSubGroup.first());
|
||||
configVO.setSubGroupId(configGroupAndSubGroup.second());
|
||||
if (c.getKind() != null) {
|
||||
configVO.setKind(c.getKind());
|
||||
}
|
||||
if (c.getOptions() != null) {
|
||||
configVO.setOptions(c.getOptions());
|
||||
}
|
||||
|
||||
_configDao.persist(configVO);
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,6 +76,7 @@ import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd;
|
||||
import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd;
|
||||
import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
|
||||
import org.apache.cloudstack.api.command.admin.cluster.UpdateClusterCmd;
|
||||
import org.apache.cloudstack.api.command.admin.config.ListCfgGroupsByCmd;
|
||||
import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
|
||||
import org.apache.cloudstack.api.command.admin.config.ListDeploymentPlannersCmd;
|
||||
import org.apache.cloudstack.api.command.admin.config.ListHypervisorCapabilitiesCmd;
|
||||
@ -582,6 +583,7 @@ import org.apache.cloudstack.api.command.user.vpn.UpdateVpnGatewayCmd;
|
||||
import org.apache.cloudstack.api.command.user.zone.ListZonesCmd;
|
||||
import org.apache.cloudstack.config.ApiServiceConfiguration;
|
||||
import org.apache.cloudstack.config.Configuration;
|
||||
import org.apache.cloudstack.config.ConfigurationGroup;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
|
||||
@ -589,6 +591,10 @@ 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.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationGroupVO;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
||||
import org.apache.cloudstack.framework.security.keystore.KeystoreManager;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
@ -858,6 +864,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
@Inject
|
||||
private ConfigurationGroupDao _configGroupDao;
|
||||
@Inject
|
||||
private ConfigurationSubGroupDao _configSubGroupDao;
|
||||
@Inject
|
||||
private ConsoleProxyManager _consoleProxyMgr;
|
||||
@Inject
|
||||
private SecondaryStorageVmManager _secStorageVmMgr;
|
||||
@ -2117,6 +2127,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
final Long imageStoreId = cmd.getImageStoreId();
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long domainId = cmd.getDomainId();
|
||||
final String groupName = cmd.getGroupName();
|
||||
final String subGroupName = cmd.getSubGroupName();
|
||||
final String parentName = cmd.getParentName();
|
||||
String scope = null;
|
||||
Long id = null;
|
||||
int paramCountCheck = 0;
|
||||
@ -2186,6 +2199,29 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%");
|
||||
}
|
||||
|
||||
if (groupName != null) {
|
||||
ConfigurationGroupVO configGroupVO = _configGroupDao.findByName(groupName);
|
||||
if (configGroupVO == null) {
|
||||
throw new InvalidParameterValueException("Invalid configuration group: " + groupName);
|
||||
}
|
||||
Long groupId = configGroupVO.getId();
|
||||
sc.addAnd("groupId", SearchCriteria.Op.EQ, groupId);
|
||||
}
|
||||
|
||||
if (subGroupName != null) {
|
||||
ConfigurationSubGroupVO configSubGroupVO = _configSubGroupDao.findByName(subGroupName);
|
||||
if (configSubGroupVO == null) {
|
||||
throw new InvalidParameterValueException("Invalid configuration subgroup: " + subGroupName);
|
||||
}
|
||||
|
||||
Long subGroupId = configSubGroupVO.getId();
|
||||
sc.addAnd("subGroupId", SearchCriteria.Op.EQ, subGroupId);
|
||||
}
|
||||
|
||||
if (parentName != null) {
|
||||
sc.addAnd("parent", SearchCriteria.Op.EQ, parentName);
|
||||
}
|
||||
|
||||
if (category != null) {
|
||||
sc.addAnd("category", SearchCriteria.Op.EQ, category);
|
||||
}
|
||||
@ -2235,6 +2271,20 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
return new Pair<List<? extends Configuration>, Integer>(result.first(), result.second());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<? extends ConfigurationGroup>, Integer> listConfigurationGroups(ListCfgGroupsByCmd cmd) {
|
||||
final Filter searchFilter = new Filter(ConfigurationGroupVO.class, "precedence", true, null, null);
|
||||
final SearchCriteria<ConfigurationGroupVO> sc = _configGroupDao.createSearchCriteria();
|
||||
|
||||
final String groupName = cmd.getGroupName();
|
||||
if (StringUtils.isNotBlank(groupName)) {
|
||||
sc.addAnd("name", SearchCriteria.Op.EQ, groupName);
|
||||
}
|
||||
|
||||
final Pair<List<ConfigurationGroupVO>, Integer> result = _configGroupDao.searchAndCount(sc, searchFilter);
|
||||
return new Pair<List<? extends ConfigurationGroup>, Integer>(result.first(), result.second());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<? extends IpAddress>, Integer> searchForIPAddresses(final ListPublicIpAddressesCmd cmd) {
|
||||
final Long associatedNetworkId = cmd.getAssociatedNetworkId();
|
||||
@ -3221,6 +3271,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
cmdList.add(ListClustersCmd.class);
|
||||
cmdList.add(UpdateClusterCmd.class);
|
||||
cmdList.add(ListCfgsByCmd.class);
|
||||
cmdList.add(ListCfgGroupsByCmd.class);
|
||||
cmdList.add(ListHypervisorCapabilitiesCmd.class);
|
||||
cmdList.add(UpdateCfgCmd.class);
|
||||
cmdList.add(UpdateHypervisorCapabilitiesCmd.class);
|
||||
|
||||
@ -624,14 +624,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
private static final ConfigKey<Boolean> EnableAdditionalVmConfig = new ConfigKey<>("Advanced", Boolean.class,
|
||||
"enable.additional.vm.configuration", "false", "allow additional arbitrary configuration to vm", true, ConfigKey.Scope.Account);
|
||||
|
||||
private static final ConfigKey<String> KvmAdditionalConfigAllowList = new ConfigKey<>("Advanced", String.class,
|
||||
"allow.additional.vm.configuration.list.kvm", "", "Comma separated list of allowed additional configuration options.", true);
|
||||
private static final ConfigKey<String> KvmAdditionalConfigAllowList = new ConfigKey<>(String.class,
|
||||
"allow.additional.vm.configuration.list.kvm", "Advanced", "", "Comma separated list of allowed additional configuration options.", true, ConfigKey.Scope.Global, null, null, EnableAdditionalVmConfig.key(), null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
private static final ConfigKey<String> XenServerAdditionalConfigAllowList = new ConfigKey<>("Advanced", String.class,
|
||||
"allow.additional.vm.configuration.list.xenserver", "", "Comma separated list of allowed additional configuration options", true);
|
||||
private static final ConfigKey<String> XenServerAdditionalConfigAllowList = new ConfigKey<>(String.class,
|
||||
"allow.additional.vm.configuration.list.xenserver", "Advanced", "", "Comma separated list of allowed additional configuration options", true, ConfigKey.Scope.Global, null, null, EnableAdditionalVmConfig.key(), null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
private static final ConfigKey<String> VmwareAdditionalConfigAllowList = new ConfigKey<>("Advanced", String.class,
|
||||
"allow.additional.vm.configuration.list.vmware", "", "Comma separated list of allowed additional configuration options.", true);
|
||||
private static final ConfigKey<String> VmwareAdditionalConfigAllowList = new ConfigKey<>(String.class,
|
||||
"allow.additional.vm.configuration.list.vmware", "Advanced", "", "Comma separated list of allowed additional configuration options.", true, ConfigKey.Scope.Global, null, null, EnableAdditionalVmConfig.key(), null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
private static final ConfigKey<Boolean> VmDestroyForcestop = new ConfigKey<Boolean>("Advanced", Boolean.class, "vm.destroy.forcestop", "false",
|
||||
"On destroy, force-stop takes this value ", true);
|
||||
|
||||
@ -50,10 +50,10 @@ import org.apache.commons.lang3.StringUtils;
|
||||
public class IndirectAgentLBServiceImpl extends ComponentLifecycleBase implements IndirectAgentLB, Configurable {
|
||||
public static final Logger LOG = Logger.getLogger(IndirectAgentLBServiceImpl.class);
|
||||
|
||||
public static final ConfigKey<String> IndirectAgentLBAlgorithm = new ConfigKey<>("Advanced", String.class,
|
||||
"indirect.agent.lb.algorithm", "static",
|
||||
public static final ConfigKey<String> IndirectAgentLBAlgorithm = new ConfigKey<>(String.class,
|
||||
"indirect.agent.lb.algorithm", "Advanced", "static",
|
||||
"The algorithm to be applied on the provided 'host' management server list that is sent to indirect agents. Allowed values are: static, roundrobin and shuffle.",
|
||||
true, ConfigKey.Scope.Global);
|
||||
true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.Select, "static,roundrobin,shuffle");
|
||||
|
||||
public static final ConfigKey<Long> IndirectAgentLBCheckInterval = new ConfigKey<>("Advanced", Long.class,
|
||||
"indirect.agent.lb.check.interval", "0",
|
||||
|
||||
@ -106,7 +106,7 @@ public class DiagnosticsServiceImpl extends ManagerBase implements PluggableServ
|
||||
"Enable the garbage collector background task to delete old files from secondary storage.", false);
|
||||
private static final ConfigKey<Integer> GarbageCollectionInterval = new ConfigKey<>("Advanced", Integer.class,
|
||||
"diagnostics.data.gc.interval", "86400",
|
||||
"The interval at which the garbage collector background tasks in seconds", false);
|
||||
"The interval at which the garbage collector background tasks in seconds", false, EnableGarbageCollector.key());
|
||||
|
||||
// These are easily computed properties and need not need a restart of the management server
|
||||
private static final ConfigKey<Long> DataRetrievalTimeout = new ConfigKey<>("Advanced", Long.class,
|
||||
@ -114,7 +114,7 @@ public class DiagnosticsServiceImpl extends ManagerBase implements PluggableServ
|
||||
"Overall system VM script execution time out in seconds.", true);
|
||||
private static final ConfigKey<Long> MaximumFileAgeforGarbageCollection = new ConfigKey<>("Advanced", Long.class,
|
||||
"diagnostics.data.max.file.age", "86400",
|
||||
"Sets the maximum time in seconds a file can stay in secondary storage before it is deleted.", true);
|
||||
"Sets the maximum time in seconds a file can stay in secondary storage before it is deleted.", true, EnableGarbageCollector.key());
|
||||
private static final ConfigKey<Double> DiskQuotaPercentageThreshold = new ConfigKey<>("Advanced", Double.class,
|
||||
"diagnostics.data.disable.threshold", "0.9",
|
||||
"Sets the secondary storage disk utilisation percentage for file retrieval. " +
|
||||
|
||||
@ -30,18 +30,18 @@ public interface DiagnosticsFilesList {
|
||||
* in the system vm and grab output for retrieval, e.g. the output from iptables-save is written to a file
|
||||
* which will then be retrieved.
|
||||
*/
|
||||
ConfigKey<String> SystemVMDefaultSupportedFiles = new ConfigKey<>("Advanced", String.class,
|
||||
"diagnostics.data.systemvm.defaults", "iptables,ipaddr,iprule,iproute,/etc/cloudstack-release," +
|
||||
ConfigKey<String> SystemVMDefaultSupportedFiles = new ConfigKey<>(String.class,
|
||||
"diagnostics.data.systemvm.defaults", "Advanced", "iptables,ipaddr,iprule,iproute,/etc/cloudstack-release," +
|
||||
"/usr/local/cloud/systemvm/conf/agent.properties,/usr/local/cloud/systemvm/conf/consoleproxy.properties," +
|
||||
"/var/log/cloud.log,/var/log/patchsystemvm.log,/var/log/daemon.log",
|
||||
"List of supported diagnostics data file options for the CPVM and SSVM.", true);
|
||||
"List of supported diagnostics data file options for the CPVM and SSVM.", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
ConfigKey<String> RouterDefaultSupportedFiles = new ConfigKey<>("Advanced", String.class,
|
||||
"diagnostics.data.router.defaults", "iptables,ipaddr,iprule,iproute,/etc/cloudstack-release," +
|
||||
ConfigKey<String> RouterDefaultSupportedFiles = new ConfigKey<>(String.class,
|
||||
"diagnostics.data.router.defaults", "Advanced", "iptables,ipaddr,iprule,iproute,/etc/cloudstack-release," +
|
||||
"/etc/dnsmasq.conf,/etc/dhcphosts.txt,/etc/dhcpopts.txt,/etc/dnsmasq.d/cloud.conf,/etc/dnsmasq-resolv.conf,/var/lib/misc/dnsmasq.leases,/var/log/dnsmasq.log," +
|
||||
"/etc/hosts,/etc/resolv.conf,/etc/haproxy/haproxy.cfg,/var/log/haproxy.log,/etc/ipsec.d/l2tp.conf,/var/log/cloud.log," +
|
||||
"/var/log/routerServiceMonitor.log,/var/log/daemon.log",
|
||||
"List of supported diagnostics data file options for the domain router.", true);
|
||||
"List of supported diagnostics data file options for the domain router.", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
List<String> generateFileList();
|
||||
}
|
||||
|
||||
@ -81,6 +81,8 @@
|
||||
<dao name="VM Template Pool" class="com.cloud.storage.dao.VMTemplatePoolDaoImpl" />
|
||||
<dao name="Launch Permission" class="com.cloud.storage.dao.LaunchPermissionDaoImpl" />
|
||||
<dao name="Configuration" class="com.cloud.configuration.dao.ConfigurationDaoImpl" />
|
||||
<dao name="Configuration Group" class="com.cloud.configuration.dao.ConfigurationGroupDaoImpl" />
|
||||
<dao name="Configuration SubGroup" class="com.cloud.configuration.dao.ConfigurationSubGroupDaoImpl" />
|
||||
<dao name="HA" class="com.cloud.ha.dao.HighAvailabilityDaoImpl" />
|
||||
<dao name="Console Proxy" class="com.cloud.vm.dao.ConsoleProxyDaoImpl" />
|
||||
<dao name="Upgrade" class="com.cloud.maint.dao.AgentUpgradeDaoImpl" />
|
||||
|
||||
@ -24,7 +24,7 @@ public class ConfigTest {
|
||||
for (Config configuration : Config.values()) {
|
||||
if (configuration.getType().equals(Integer.class) && configuration.getRange() != null) {
|
||||
try {
|
||||
final String[] options = configuration.getRange()[0].split("-");
|
||||
final String[] options = configuration.getRange().split("-");
|
||||
final int min = Integer.parseInt(options[0]);
|
||||
final int max = Integer.parseInt(options[1]);
|
||||
if (options.length != 2) {
|
||||
|
||||
@ -31,6 +31,8 @@ import org.springframework.core.type.filter.TypeFilter;
|
||||
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl;
|
||||
import org.apache.cloudstack.test.utils.SpringUtils;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
@ -70,8 +72,8 @@ import com.cloud.vm.dao.UserVmDetailsDaoImpl;
|
||||
import com.cloud.vm.dao.VMInstanceDaoImpl;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = {SecurityGroupRulesDaoImpl.class, UserVmDaoImpl.class, AccountDaoImpl.class, ConfigurationDaoImpl.class,
|
||||
SecurityGroupWorkDaoImpl.class, VmRulesetLogDaoImpl.class, VMInstanceDaoImpl.class, DomainDaoImpl.class, UsageEventDaoImpl.class,
|
||||
@ComponentScan(basePackageClasses = {SecurityGroupRulesDaoImpl.class, UserVmDaoImpl.class, AccountDaoImpl.class, ConfigurationDaoImpl.class, ConfigurationGroupDaoImpl.class,
|
||||
ConfigurationSubGroupDaoImpl.class, SecurityGroupWorkDaoImpl.class, VmRulesetLogDaoImpl.class, VMInstanceDaoImpl.class, DomainDaoImpl.class, UsageEventDaoImpl.class,
|
||||
ResourceTagsDaoImpl.class, HostDaoImpl.class, HostDetailsDaoImpl.class, HostTagsDaoImpl.class, ClusterDaoImpl.class, HostPodDaoImpl.class,
|
||||
DataCenterDaoImpl.class, DataCenterIpAddressDaoImpl.class, HostTransferMapDaoImpl.class, SecurityGroupManagerImpl2.class, SecurityGroupDaoImpl.class,
|
||||
SecurityGroupVMMapDaoImpl.class, UserVmDetailsDaoImpl.class, DataCenterIpAddressDaoImpl.class, DataCenterLinkLocalIpAddressDaoImpl.class,
|
||||
|
||||
@ -37,6 +37,8 @@ import org.apache.cloudstack.framework.config.ConfigDepot;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.ScopedConfigStorage;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDao;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDao;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
@ -116,6 +118,10 @@ public class FirstFitPlannerTest {
|
||||
@Inject
|
||||
ConfigurationDao configDao;
|
||||
@Inject
|
||||
ConfigurationGroupDao configGroupDao;
|
||||
@Inject
|
||||
ConfigurationSubGroupDao configSubGroupDao;
|
||||
@Inject
|
||||
CapacityDao capacityDao;
|
||||
@Inject
|
||||
AccountManager accountMgr;
|
||||
@ -431,6 +437,16 @@ public class FirstFitPlannerTest {
|
||||
return Mockito.mock(ConfigurationDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurationGroupDao configurationGroupDao() {
|
||||
return Mockito.mock(ConfigurationGroupDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurationSubGroupDao configurationSubGroupDao() {
|
||||
return Mockito.mock(ConfigurationSubGroupDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PrimaryDataStoreDao primaryDataStoreDao() {
|
||||
return Mockito.mock(PrimaryDataStoreDao.class);
|
||||
|
||||
@ -56,6 +56,7 @@ import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd;
|
||||
import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd;
|
||||
import org.apache.cloudstack.config.Configuration;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO;
|
||||
import org.apache.cloudstack.region.PortableIp;
|
||||
import org.apache.cloudstack.region.PortableIpRange;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -661,4 +662,21 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigurationType(String configName) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<String, String> getConfigurationGroupAndSubGroup(String configName) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConfigurationSubGroupVO> getConfigurationSubGroups(Long groupId) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +30,8 @@ import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl;
|
||||
import org.apache.cloudstack.test.utils.SpringUtils;
|
||||
|
||||
import com.cloud.alert.AlertManager;
|
||||
@ -107,9 +109,9 @@ import com.cloud.vpc.dao.MockVpcOfferingDaoImpl;
|
||||
import com.cloud.vpc.dao.MockVpcOfferingServiceMapDaoImpl;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = {VpcManagerImpl.class, NetworkElement.class, VpcOfferingDao.class, ConfigurationDaoImpl.class, IPAddressDaoImpl.class,
|
||||
DomainRouterDaoImpl.class, VpcGatewayDaoImpl.class, PrivateIpDaoImpl.class, StaticRouteDaoImpl.class, PhysicalNetworkDaoImpl.class,
|
||||
ResourceTagsDaoImpl.class, FirewallRulesDaoImpl.class, VlanDaoImpl.class, AccountDaoImpl.class, ResourceCountDaoImpl.class,
|
||||
@ComponentScan(basePackageClasses = {VpcManagerImpl.class, NetworkElement.class, VpcOfferingDao.class, ConfigurationDaoImpl.class, ConfigurationGroupDaoImpl.class,
|
||||
ConfigurationSubGroupDaoImpl.class, IPAddressDaoImpl.class, DomainRouterDaoImpl.class, VpcGatewayDaoImpl.class, PrivateIpDaoImpl.class, StaticRouteDaoImpl.class,
|
||||
PhysicalNetworkDaoImpl.class, ResourceTagsDaoImpl.class, FirewallRulesDaoImpl.class, VlanDaoImpl.class, AccountDaoImpl.class, ResourceCountDaoImpl.class,
|
||||
Site2SiteVpnGatewayDaoImpl.class, PodVlanMapDaoImpl.class, AccountVlanMapDaoImpl.class, DomainVlanMapDaoImpl.class, HostDaoImpl.class, HostDetailsDaoImpl.class,
|
||||
HostTagsDaoImpl.class, HostTransferMapDaoImpl.class, ClusterDaoImpl.class, HostPodDaoImpl.class, RouterNetworkDaoImpl.class,
|
||||
UserStatisticsDaoImpl.class, PhysicalNetworkTrafficTypeDaoImpl.class, FirewallRulesCidrsDaoImpl.class, ResourceLimitManagerImpl.class,
|
||||
|
||||
@ -19,7 +19,6 @@ package com.cloud.vpc.dao;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
|
||||
|
||||
|
||||
@ -70,4 +70,6 @@
|
||||
<bean id="VsphereStoragePolicyDaoImpl" class="com.cloud.dc.dao.VsphereStoragePolicyDaoImpl" />
|
||||
<bean id="annotationDaoImpl" class="org.apache.cloudstack.annotation.dao.AnnotationDaoImpl" />
|
||||
<bean id="PassphraseDaoImpl" class="org.apache.cloudstack.secret.dao.PassphraseDaoImpl" />
|
||||
<bean id="configurationGroupDaoImpl" class="org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl" />
|
||||
<bean id="configurationSubGroupDaoImpl" class="org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl" />
|
||||
</beans>
|
||||
|
||||
@ -267,7 +267,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
|
||||
private final GlobalLock _allocLock = GlobalLock.getInternLock(getAllocLockName());
|
||||
|
||||
static final ConfigKey<String> NTPServerConfig = new ConfigKey<String>(String.class, "ntp.server.list", "Advanced", null,
|
||||
"Comma separated list of NTP servers to configure in Secondary storage VM", true, ConfigKey.Scope.Global, null);
|
||||
"Comma separated list of NTP servers to configure in Secondary storage VM", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
static final ConfigKey<Integer> MaxNumberOfSsvmsForMigration = new ConfigKey<Integer>("Advanced", Integer.class, "max.ssvm.count", "5",
|
||||
"Number of additional SSVMs to handle migration of data objects concurrently", true, ConfigKey.Scope.Global);
|
||||
|
||||
@ -75,3 +75,109 @@ class TestUpdateConfigWithScope(cloudstackTestCase):
|
||||
updateConfigurationCmd.scopename = "zone"
|
||||
updateConfigurationCmd.scopeid = 1
|
||||
self.apiClient.updateConfiguration(updateConfigurationCmd)
|
||||
|
||||
class TestListConfigurations(cloudstackTestCase):
|
||||
"""
|
||||
Test to list configurations (global settings)
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.apiclient = cls.testClient.getApiClient()
|
||||
cls._cleanup = []
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(TestListConfigurations, cls).tearDownClass()
|
||||
|
||||
def setUp(self):
|
||||
self.apiClient = self.testClient.getApiClient()
|
||||
self.cleanup = []
|
||||
|
||||
def tearDown(self):
|
||||
super(TestListConfigurations, self).tearDown()
|
||||
|
||||
@attr(tags=["devcloud", "basic", "advanced"], required_hardware="false")
|
||||
def test_01_list_configs(self):
|
||||
"""
|
||||
test list configuration setting at global level
|
||||
@return:
|
||||
"""
|
||||
listConfigurationsCmd = listConfigurations.listConfigurationsCmd()
|
||||
|
||||
listConfigurationsCmd.name = "agent.lb.enabled"
|
||||
listConfigurationsResponse = self.apiClient.listConfigurations(listConfigurationsCmd)
|
||||
self.assertNotEqual(len(listConfigurationsResponse), 0, "Check if the list configurations API returns a non-empty response")
|
||||
self.debug("The parameter %s listed with value %s" %(listConfigurationsCmd.name, listConfigurationsResponse[0].value))
|
||||
self.assertEqual(listConfigurationsResponse[0].type, 'Boolean', "Wrong type for the config")
|
||||
self.assertEqual(listConfigurationsResponse[0].defaultvalue, 'false', "Wrong default value for the config")
|
||||
self.assertEqual(listConfigurationsResponse[0].group, 'Management Server', "Check the group for the config")
|
||||
self.assertEqual(listConfigurationsResponse[0].subgroup, 'Agent', "Check the subgroup for the config")
|
||||
|
||||
listConfigurationsCmd.name = "storage.cleanup.interval"
|
||||
listConfigurationsResponse = self.apiClient.listConfigurations(listConfigurationsCmd)
|
||||
self.assertNotEqual(len(listConfigurationsResponse), 0, "Check if the list configurations API returns a non-empty response")
|
||||
self.debug("The parameter %s listed with value %s" % (listConfigurationsCmd.name, listConfigurationsResponse[0].value))
|
||||
self.assertEqual(listConfigurationsResponse[0].type, 'Number', "Wrong type for the config")
|
||||
self.assertEqual(listConfigurationsResponse[0].defaultvalue, '86400', "Wrong default value for the config")
|
||||
self.assertEqual(listConfigurationsResponse[0].group, 'Infrastructure', "Check the group for the config")
|
||||
self.assertEqual(listConfigurationsResponse[0].subgroup, 'Primary Storage', "Check the subgroup for the config")
|
||||
|
||||
listConfigurationsCmd.name = "agent.load.threshold"
|
||||
listConfigurationsResponse = self.apiClient.listConfigurations(listConfigurationsCmd)
|
||||
self.assertNotEqual(len(listConfigurationsResponse), 0, "Check if the list configurations API returns a non-empty response")
|
||||
self.debug("The parameter %s listed with value %s" % (listConfigurationsCmd.name, listConfigurationsResponse[0].value))
|
||||
self.assertEqual(listConfigurationsResponse[0].type, 'Range', "Wrong type for the config")
|
||||
self.assertEqual(listConfigurationsResponse[0].defaultvalue, '0.7', "Wrong default value for the config")
|
||||
self.assertEqual(listConfigurationsResponse[0].group, 'Management Server', "Check the group for the config")
|
||||
self.assertEqual(listConfigurationsResponse[0].subgroup, 'Agent', "Check the subgroup for the config")
|
||||
|
||||
listConfigurationsCmd.name = "endpoint.url"
|
||||
listConfigurationsResponse = self.apiClient.listConfigurations(listConfigurationsCmd)
|
||||
self.assertNotEqual(len(listConfigurationsResponse), 0, "Check if the list configurations API returns a non-empty response")
|
||||
self.debug("The parameter %s listed with value %s" % (listConfigurationsCmd.name, listConfigurationsResponse[0].value))
|
||||
self.assertEqual(listConfigurationsResponse[0].type, 'String', "Wrong type for the config")
|
||||
self.assertEqual(listConfigurationsResponse[0].defaultvalue, 'http://localhost:8080/client/api', "Wrong default value for the config")
|
||||
|
||||
@attr(tags=["devcloud", "basic", "advanced"], required_hardware="false")
|
||||
def test_02_list_config_parent(self):
|
||||
"""
|
||||
test list configuration setting parent
|
||||
@return:
|
||||
"""
|
||||
listConfigurationsCmd = listConfigurations.listConfigurationsCmd()
|
||||
|
||||
listConfigurationsCmd.name = "api.throttling.cachesize"
|
||||
listConfigurationsResponse = self.apiClient.listConfigurations(listConfigurationsCmd)
|
||||
self.assertNotEqual(len(listConfigurationsResponse), 0, "Check if the list configurations API returns a non-empty response")
|
||||
self.assertEqual(listConfigurationsResponse[0].parent, 'api.throttling.enabled', "Wrong parent for the config")
|
||||
|
||||
listConfigurationsCmd.name = "storage.cache.replacement.interval"
|
||||
listConfigurationsResponse = self.apiClient.listConfigurations(listConfigurationsCmd)
|
||||
self.assertNotEqual(len(listConfigurationsResponse), 0, "Check if the list configurations API returns a non-empty response")
|
||||
self.assertEqual(listConfigurationsResponse[0].parent, 'storage.cache.replacement.enabled', "Wrong parent for the config")
|
||||
|
||||
listConfigurationsCmd.name = "cloud.kubernetes.cluster.max.size"
|
||||
listConfigurationsResponse = self.apiClient.listConfigurations(listConfigurationsCmd)
|
||||
self.assertNotEqual(len(listConfigurationsResponse), 0, "Check if the list configurations API returns a non-empty response")
|
||||
self.assertEqual(listConfigurationsResponse[0].parent, 'cloud.kubernetes.service.enabled', "Wrong parent for the config")
|
||||
|
||||
@attr(tags=["devcloud", "basic", "advanced"], required_hardware="false")
|
||||
def test_03_config_groups(self):
|
||||
"""
|
||||
test list configuration groups
|
||||
@return:
|
||||
"""
|
||||
listConfigurationGroupsResponse = Configurations.listGroups(self.apiclient)
|
||||
self.assertNotEqual(len(listConfigurationGroupsResponse), 0, "Check if the list configurationgroups API returns a non-empty response")
|
||||
|
||||
self.debug("Total %d configuration groups listed" %(len(listConfigurationGroupsResponse)))
|
||||
self.debug("Configuration groups: %s" % (str(listConfigurationGroupsResponse)))
|
||||
|
||||
group = listConfigurationGroupsResponse[0].name
|
||||
subgroup = listConfigurationGroupsResponse[0].subgroup[0].name
|
||||
|
||||
listConfigurationsResponse = Configurations.list(self.apiclient,
|
||||
group=group,
|
||||
subgroup=subgroup)
|
||||
self.assertNotEqual(len(listConfigurationsResponse), 0, "Check if the list configurations API returns a non-empty response")
|
||||
self.debug("Total %d configurations for group %s, subgroup %s" % (len(listConfigurationsResponse), group, subgroup))
|
||||
|
||||
@ -4653,6 +4653,14 @@ class Configurations:
|
||||
return (apiclient.listCapabilities(cmd))
|
||||
|
||||
|
||||
@classmethod
|
||||
def listGroups(cls, apiclient, **kwargs):
|
||||
"""Lists configuration groups"""
|
||||
cmd = listConfigurationGroups.listConfigurationGroupsCmd()
|
||||
[setattr(cmd, k, v) for k, v in list(kwargs.items())]
|
||||
return (apiclient.listConfigurationGroups(cmd))
|
||||
|
||||
|
||||
@classmethod
|
||||
def reset(cls, apiclient, name, zoneid=None, clusterid=None, storageid=None, domainid=None, accountid=None):
|
||||
"""Resets the specified configuration to original value"""
|
||||
|
||||
@ -778,7 +778,7 @@
|
||||
"label.fwdeviceid": "ID",
|
||||
"label.fwdevicestate": "Status",
|
||||
"label.gateway": "Gateway",
|
||||
"label.global.settings": "Global settings",
|
||||
"label.global.settings": "Global Settings",
|
||||
"label.globo.dns": "GloboDNS",
|
||||
"label.globo.dns.configuration": "GloboDNS configuration",
|
||||
"label.glustervolume": "Volume",
|
||||
@ -2598,6 +2598,7 @@
|
||||
"message.scaleup.policy.name.continue": "Please input a name to ScaleUp policy to continue",
|
||||
"message.select.a.zone": "A zone typically corresponds to a single datacenter. Multiple zones help make the cloud more reliable by providing physical isolation and redundancy.",
|
||||
"message.select.affinity.groups": "Please select any affinity groups you want this VM to belong to:",
|
||||
"message.select.deselect.to.sort": "Please select / deselect to sort the values",
|
||||
"message.select.destination.image.stores": "Please select Image Store(s) to which data is to be migrated to",
|
||||
"message.select.disk.offering": "Please select a disk offering for disk",
|
||||
"message.select.end.date.and.time": "Select an end date & time.",
|
||||
@ -2720,6 +2721,7 @@
|
||||
"message.template.type.change.warning": "WARNING: Changing the template type to SYSTEM will disable further changes to the template.",
|
||||
"message.tooltip.reserved.system.netmask": "The network prefix that defines the pod subnet. Uses CIDR notation.",
|
||||
"message.traffic.type.to.basic.zone": "traffic type to basic zone",
|
||||
"message.type.values.to.add": "Please add additonal values by typing them in",
|
||||
"message.update.autoscale.policy.failed": "Failed to update autoscale policy",
|
||||
"message.update.autoscale.vmgroup.failed": "Failed to update autoscale vm group",
|
||||
"message.update.autoscale.vm.profile.failed": "Failed to update autoscale vm profile",
|
||||
|
||||
@ -105,6 +105,7 @@
|
||||
<router-link v-else :to="{ path: $route.path + '/' + record.name }" >{{ text }}</router-link>
|
||||
</span>
|
||||
<span v-else-if="$route.path.startsWith('/globalsetting')">{{ text }}</span>
|
||||
<span v-else-if="$route.path.startsWith('/preferences')">{{ text }}</span>
|
||||
<span v-else-if="$route.path.startsWith('/alert')">
|
||||
<router-link :to="{ path: $route.path + '/' + record.id }" v-if="record.id">{{ $t(text.toLowerCase()) }}</router-link>
|
||||
<router-link :to="{ path: $route.path + '/' + record.name }" v-else>{{ $t(text.toLowerCase()) }}</router-link>
|
||||
|
||||
@ -26,7 +26,9 @@ export default {
|
||||
title: 'label.global.settings',
|
||||
icon: 'setting-outlined',
|
||||
permission: ['listConfigurations'],
|
||||
columns: ['name', 'description', 'category', 'value', 'actions']
|
||||
listView: true,
|
||||
popup: true,
|
||||
component: () => import('@/views/setting/ConfigurationTab.vue')
|
||||
},
|
||||
{
|
||||
name: 'ldapsetting',
|
||||
|
||||
@ -400,6 +400,10 @@ a {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.child-row {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.tag-disabled-input, .btn-add-tag {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
90
ui/src/views/setting/ConfigurationHierarchy.vue
Normal file
90
ui/src/views/setting/ConfigurationHierarchy.vue
Normal file
@ -0,0 +1,90 @@
|
||||
// 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.
|
||||
|
||||
<template>
|
||||
<a-table
|
||||
size="small"
|
||||
:showHeader="false"
|
||||
:columns="columns"
|
||||
:dataSource="config"
|
||||
:rowKey="record => record.name"
|
||||
:pagination="false"
|
||||
:rowClassName="getRowClassName"
|
||||
style="overflow-y: auto; margin-left: 10px" >
|
||||
|
||||
<template #name="{ record }">
|
||||
<span :style="hierarchyExists ? 'padding-left: 0px;' : 'padding-left: 25px;'">
|
||||
<b><span v-if="record.parent">└─ </span>{{record.displaytext }} </b> {{ ' (' + record.name + ')' }}
|
||||
</span>
|
||||
<br/>
|
||||
<span :style="record.parent ? 'padding-left: 50px; display:block' : 'padding-left: 25px; display:block'">{{ record.description }}</span>
|
||||
</template>
|
||||
|
||||
<template #value="{ record }">
|
||||
<ConfigurationValue :configrecord="record" />
|
||||
</template>
|
||||
|
||||
</a-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ConfigurationValue from './ConfigurationValue'
|
||||
|
||||
export default {
|
||||
name: 'ConfigurationHierarchy',
|
||||
components: {
|
||||
ConfigurationValue
|
||||
},
|
||||
props: {
|
||||
config: {
|
||||
type: Array,
|
||||
default: () => { return [] }
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => { return [] }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hierarchyExists () {
|
||||
for (var c of this.config) {
|
||||
if (c.children) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
apiName: 'listConfigurations',
|
||||
configdata: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getRowClassName (record, index) {
|
||||
if (record.parent) {
|
||||
return 'child-row'
|
||||
}
|
||||
if (index % 2 === 0) {
|
||||
return 'light-row'
|
||||
}
|
||||
return 'dark-row'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
365
ui/src/views/setting/ConfigurationTab.vue
Normal file
365
ui/src/views/setting/ConfigurationTab.vue
Normal file
@ -0,0 +1,365 @@
|
||||
// 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.
|
||||
|
||||
<template>
|
||||
<a-row :gutter="12">
|
||||
<a-col :md="24">
|
||||
<a-card class="breadcrumb-card">
|
||||
<a-col :span="12" style="display: inline-flex">
|
||||
<breadcrumb style="padding-top: 6px; padding-left: 8px" />
|
||||
<a-button
|
||||
style="margin-left: 12px; margin-top: 4px"
|
||||
:loading="loading"
|
||||
size="small"
|
||||
shape="round"
|
||||
@click="fetchConfigurationData()" >
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
{{ $t('label.refresh') }}
|
||||
</a-button>
|
||||
</a-col>
|
||||
<a-col :span="12" style="float: right">
|
||||
<a-input-search
|
||||
style="width: 25vw; float: right; margin-bottom: 10px; z-index: 8; display: flex"
|
||||
:placeholder="$t('label.search')"
|
||||
v-model:value="filter"
|
||||
@search="changePage()"
|
||||
v-focus="true" />
|
||||
</a-col>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-card style="margin-left: 10px;">
|
||||
<a-spin :spinning="configLoading">
|
||||
<a-tabs
|
||||
tabPosition="left"
|
||||
:animated="false"
|
||||
:activeKey="this.group || ''"
|
||||
@change="changeGroupTab" >
|
||||
<a-tab-pane
|
||||
key=''
|
||||
tab='All Settings' >
|
||||
<ConfigurationTable
|
||||
:columns="columns"
|
||||
:config="config"
|
||||
:count="count"
|
||||
:page="page"
|
||||
:pagesize="pagesize"
|
||||
@change-page="changePage" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane
|
||||
v-for="(group) in groups"
|
||||
:key="group.name"
|
||||
:tab="group.name" >
|
||||
<a-tabs
|
||||
:activeKey="this.subgroup || ''"
|
||||
:animated="false"
|
||||
@change="changeSubgroupTab" >
|
||||
<a-tab-pane
|
||||
v-for="(subgroup) in group.subgroup"
|
||||
:key="subgroup.name"
|
||||
:tab="subgroup.name" >
|
||||
<ConfigurationHierarchy
|
||||
:columns="columns"
|
||||
:config="config" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-spin>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { api } from '@/api'
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import Breadcrumb from '@/components/widgets/Breadcrumb'
|
||||
import OsLogo from '@/components/widgets/OsLogo'
|
||||
import Status from '@/components/widgets/Status'
|
||||
import ActionButton from '@/components/view/ActionButton'
|
||||
import InfoCard from '@/components/view/InfoCard'
|
||||
import QuickView from '@/components/view/QuickView'
|
||||
import TooltipButton from '@/components/widgets/TooltipButton'
|
||||
import ConfigurationHierarchy from './ConfigurationHierarchy'
|
||||
import ConfigurationTable from './ConfigurationTable'
|
||||
|
||||
export default {
|
||||
name: 'ConfigurationTab',
|
||||
components: {
|
||||
Breadcrumb,
|
||||
OsLogo,
|
||||
Status,
|
||||
ActionButton,
|
||||
InfoCard,
|
||||
QuickView,
|
||||
TooltipButton,
|
||||
ConfigurationHierarchy,
|
||||
ConfigurationTable
|
||||
},
|
||||
mixins: [mixin, mixinDevice],
|
||||
props: {
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
actions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
groups: [],
|
||||
config: [],
|
||||
configLoading: true,
|
||||
page: 1,
|
||||
pagesize: this.$store.getters.defaultListViewPageSize,
|
||||
group: '',
|
||||
subgroup: '',
|
||||
filter: '',
|
||||
count: 0,
|
||||
apiName: 'listConfigurations',
|
||||
columns: [
|
||||
{
|
||||
title: 'name',
|
||||
dataIndex: 'name',
|
||||
slots: { customRender: 'name' }
|
||||
},
|
||||
{
|
||||
title: 'value',
|
||||
dataIndex: 'value',
|
||||
slots: { customRender: 'value' },
|
||||
width: '29%'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route.fullPath': function () {
|
||||
this.group = this.$route.query.group || ''
|
||||
this.subgroup = this.$route.query.subgroup || ''
|
||||
this.page = parseInt(this.$route.query.page) || 1
|
||||
this.pagesize = parseInt(this.$route.query.pagesize) || this.pagesize
|
||||
this.filter = this.$route.query.filter || ''
|
||||
this.fetchConfigurationData()
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.fetchConfigurationGroups()
|
||||
},
|
||||
methods: {
|
||||
fetchConfigurationGroups () {
|
||||
this.configLoading = true
|
||||
const params = {
|
||||
pagesize: -1
|
||||
}
|
||||
api('listConfigurationGroups', params).then(response => {
|
||||
this.groups = response.listconfigurationgroupsresponse.configurationgroup
|
||||
}).catch(error => {
|
||||
console.error(error)
|
||||
this.$message.error(this.$t('message.error.loading.setting'))
|
||||
}).finally(() => {
|
||||
this.group = this.$route.query.group || ''
|
||||
this.subgroup = this.$route.query.subgroup || ''
|
||||
this.fetchConfigurationData()
|
||||
})
|
||||
},
|
||||
fetchConfigurationData () {
|
||||
this.configLoading = true
|
||||
const params = {
|
||||
listAll: true
|
||||
}
|
||||
if (this.group.length > 0) {
|
||||
params.group = this.group
|
||||
params.pagesize = -1
|
||||
} else {
|
||||
params.pagesize = this.pagesize || 20
|
||||
params.page = this.page || 1
|
||||
}
|
||||
if (this.subgroup.length > 0) {
|
||||
params.subgroup = this.subgroup
|
||||
}
|
||||
if (this.filter) {
|
||||
params.keyword = this.filter
|
||||
}
|
||||
|
||||
api('listConfigurations', params).then(response => {
|
||||
this.config = []
|
||||
let config = response.listconfigurationsresponse.configuration || []
|
||||
this.count = response.listconfigurationsresponse.count || 0
|
||||
if (this.group.length > 0) {
|
||||
config = this.convertConfigToHierarchy(config)
|
||||
}
|
||||
this.config = config
|
||||
window.scrollTo(0, 0)
|
||||
}).catch(error => {
|
||||
console.error(error)
|
||||
this.$message.error(this.$t('message.error.loading.setting'))
|
||||
}).finally(() => {
|
||||
this.configLoading = false
|
||||
})
|
||||
},
|
||||
convertConfigToHierarchy (config) {
|
||||
var hierarchy = {}
|
||||
for (var c of config) {
|
||||
if (c.parent && c.parent.length !== 0) {
|
||||
if (hierarchy[c.parent]) {
|
||||
hierarchy[c.parent].push(c)
|
||||
} else {
|
||||
hierarchy[c.parent] = [c]
|
||||
}
|
||||
}
|
||||
}
|
||||
for (c of config) {
|
||||
if (hierarchy[c.name]) {
|
||||
c.children = hierarchy[c.name]
|
||||
}
|
||||
}
|
||||
config = config.filter(c => !c.parent)
|
||||
return config
|
||||
},
|
||||
changePage (page, pagesize) {
|
||||
const query = {}
|
||||
if (page) {
|
||||
query.page = page
|
||||
this.page = page
|
||||
} else {
|
||||
this.page = 1
|
||||
}
|
||||
if (pagesize) {
|
||||
query.pagesize = pagesize
|
||||
this.pagesize = pagesize
|
||||
}
|
||||
if (this.filter) {
|
||||
query.filter = this.filter
|
||||
}
|
||||
if (this.group !== '') {
|
||||
query.group = this.group
|
||||
}
|
||||
if (this.subgroup !== '') {
|
||||
query.subgroup = this.subgroup
|
||||
}
|
||||
this.pushToHistory(query)
|
||||
this.fetchConfigurationData()
|
||||
},
|
||||
pushToHistory (query) {
|
||||
history.pushState(
|
||||
{},
|
||||
null,
|
||||
'#' + this.$route.path + '?' + Object.keys(query).map(key => {
|
||||
return (
|
||||
encodeURIComponent(key) + '=' + encodeURIComponent(query[key])
|
||||
)
|
||||
}).join('&')
|
||||
)
|
||||
},
|
||||
changeGroupTab (e) {
|
||||
this.group = e
|
||||
if (this.group.length > 0) {
|
||||
for (const groupIndex in this.groups) {
|
||||
if (this.groups[groupIndex].name === this.group) {
|
||||
const group = this.groups[groupIndex]
|
||||
this.subgroup = group.subgroup[0].name
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.group = ''
|
||||
this.subgroup = ''
|
||||
this.changePage(1, this.pagesize)
|
||||
}
|
||||
if (this.group.length > 0 && this.subgroup.length > 0) {
|
||||
const query = Object.assign({}, this.$route.query)
|
||||
delete query.page
|
||||
delete query.pagesize
|
||||
query.group = this.group
|
||||
query.subgroup = this.subgroup
|
||||
query.filter = this.filter
|
||||
// this.pagesize = -1
|
||||
this.page = 0
|
||||
this.pushToHistory(query)
|
||||
this.fetchConfigurationData()
|
||||
}
|
||||
},
|
||||
changeSubgroupTab (e) {
|
||||
this.subgroup = e || this.subgroup
|
||||
if (this.group.length > 0 && this.subgroup.length > 0) {
|
||||
const query = Object.assign({}, this.$route.query)
|
||||
delete query.page
|
||||
delete query.pagesize
|
||||
query.group = this.group
|
||||
query.subgroup = this.subgroup
|
||||
// this.pagesize = -1
|
||||
this.page = 0
|
||||
this.pushToHistory(query)
|
||||
this.fetchConfigurationData()
|
||||
} else {
|
||||
history.pushState(
|
||||
{},
|
||||
null,
|
||||
'#' + this.$route.path
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.breadcrumb-card {
|
||||
margin-left: -24px;
|
||||
margin-right: -24px;
|
||||
margin-top: -16px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.shift-btns {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.shift-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 12px;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
&--rotated {
|
||||
font-size: 10px;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.alert-notification-threshold {
|
||||
background-color: rgba(255, 231, 175, 0.75);
|
||||
color: #e87900;
|
||||
padding: 10%;
|
||||
}
|
||||
|
||||
.alert-disable-threshold {
|
||||
background-color: rgba(255, 190, 190, 0.75);
|
||||
color: #f50000;
|
||||
padding: 10%;
|
||||
}
|
||||
</style>
|
||||
191
ui/src/views/setting/ConfigurationTable.vue
Normal file
191
ui/src/views/setting/ConfigurationTable.vue
Normal file
@ -0,0 +1,191 @@
|
||||
// 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.
|
||||
|
||||
<template>
|
||||
<div class="config-row-element">
|
||||
<a-table
|
||||
class="config-list-view"
|
||||
size="small"
|
||||
:showHeader="false"
|
||||
:pagination="false"
|
||||
:columns="columns"
|
||||
:dataSource="config"
|
||||
:rowKey="record => record.name"
|
||||
:rowClassName="getRowClassName" >
|
||||
|
||||
<template #name="{ record }">
|
||||
<b> {{record.displaytext }} </b> {{ ' (' + record.name + ')' }} <br/> {{ record.description }}
|
||||
</template>
|
||||
<template #value="{ record }">
|
||||
<ConfigurationValue :configrecord="record" />
|
||||
</template>
|
||||
</a-table>
|
||||
<a-pagination
|
||||
class="config-row-element"
|
||||
style="margin-top: 10px"
|
||||
size="small"
|
||||
:current="page"
|
||||
:pageSize="pagesize"
|
||||
:total="count"
|
||||
:showTotal="count => `${$t('label.showing')} ${Math.min(count, 1+((page-1)*pagesize))}-${Math.min(page*pagesize, count)} ${$t('label.of')} ${count} ${$t('label.items')}`"
|
||||
:pageSizeOptions="pageSizeOptions"
|
||||
@change="changePage"
|
||||
@showSizeChange="changePage"
|
||||
showSizeChanger
|
||||
showQuickJumper>
|
||||
<template #buildOptionText="props">
|
||||
<span>{{ props.value }} / {{ $t('label.page') }}</span>
|
||||
</template>
|
||||
</a-pagination>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ConfigurationValue from './ConfigurationValue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ConfigurationValue
|
||||
},
|
||||
name: 'ConfigurationTable',
|
||||
props: {
|
||||
config: {
|
||||
type: Array,
|
||||
default: () => { return [] }
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => { return [] }
|
||||
},
|
||||
count: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
page: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
pagesize: {
|
||||
type: Number,
|
||||
default: 20
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
apiName: 'listConfigurations'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pageSizeOptions () {
|
||||
var sizes = [20, 50, 100, 200, this.$store.getters.defaultListViewPageSize]
|
||||
return [...new Set(sizes)].sort(function (a, b) {
|
||||
return a - b
|
||||
}).map(String)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changePage (page, pagesize) {
|
||||
this.$emit('change-page', page, pagesize)
|
||||
},
|
||||
getRowClassName (record, index) {
|
||||
if (index % 2 === 0) {
|
||||
return 'config-light-row'
|
||||
}
|
||||
return 'config-dark-row'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.list {
|
||||
clear:both;
|
||||
}
|
||||
.editable-value {
|
||||
|
||||
@media (min-width: 760px) {
|
||||
text-align: right;
|
||||
margin-left: 40px;
|
||||
margin-right: -40px;
|
||||
}
|
||||
|
||||
}
|
||||
.item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
|
||||
@media (min-width: 760px) {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&__content {
|
||||
width: 100%;
|
||||
display: block;
|
||||
word-break: break-all;
|
||||
|
||||
@media (min-width: 760px) {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.action {
|
||||
margin-top: 20px;
|
||||
margin-left: -12px;
|
||||
|
||||
@media (min-width: 480px) {
|
||||
margin-left: -24px;
|
||||
}
|
||||
|
||||
@media (min-width: 760px) {
|
||||
margin-top: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.value {
|
||||
margin-top: 20px;
|
||||
|
||||
@media (min-width: 760px) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.config-light-row {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.config-dark-row {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.config-row-element {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.config-list-view {
|
||||
overflow-y: auto;
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
</style>
|
||||
363
ui/src/views/setting/ConfigurationValue.vue
Normal file
363
ui/src/views/setting/ConfigurationValue.vue
Normal file
@ -0,0 +1,363 @@
|
||||
// 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.
|
||||
|
||||
<template>
|
||||
<a-list>
|
||||
<a-list-item>
|
||||
<span v-if="configrecord.type ==='Boolean'">
|
||||
<a-tooltip :title="editableValue?'true':'false'">
|
||||
<a-switch
|
||||
:disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
|
||||
v-model:checked="editableValue"
|
||||
@keydown.esc="editableValueKey = null"
|
||||
@pressEnter="updateConfigurationValue(configrecord)"
|
||||
@change="value => setConfigurationEditable(configrecord, value)"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span v-else-if="configrecord.type ==='Number'">
|
||||
<a-tooltip :title="editableValue">
|
||||
<a-input-number
|
||||
style="width: 20vw;"
|
||||
:defaultValue="actualValue"
|
||||
:disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
|
||||
v-model:value="editableValue"
|
||||
@keydown.esc="editableValueKey = null"
|
||||
@pressEnter="updateConfigurationValue(configrecord)"
|
||||
@change="value => setConfigurationEditable(configrecord, value)"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span v-else-if="configrecord.type ==='Decimal'">
|
||||
<a-tooltip :title="editableValue">
|
||||
<a-input-number
|
||||
style="width: 20vw"
|
||||
:defaultValue="actualValue"
|
||||
:disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
|
||||
v-model:value="editableValue"
|
||||
@keydown.esc="editableValueKey = null"
|
||||
@pressEnter="updateConfigurationValue(configrecord)"
|
||||
@change="value => setConfigurationEditable(configrecord, value)"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span v-else-if="configrecord.type ==='Range'">
|
||||
<a-row>
|
||||
<a-col>
|
||||
<a-tooltip :title="editableValue">
|
||||
<a-slider
|
||||
style="width: 13vw"
|
||||
class="config-slider-value"
|
||||
:defaultValue="configrecord.value * 100"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
|
||||
v-model:value="editableValue"
|
||||
@keydown.esc="editableValueKey = null"
|
||||
@pressEnter="updateConfigurationValue(configrecord)"
|
||||
@change="value => setConfigurationEditable(configrecord, value)"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
<a-col>
|
||||
<a-tooltip :title="editableValue">
|
||||
<a-input-number
|
||||
style="width: 5vw; margin-left: 10px; float: right"
|
||||
class="config-slider-text"
|
||||
:defaultValue="configrecord.value * 100"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
|
||||
:formatter="(value) => `${value}%`"
|
||||
v-model:value="editableValue"
|
||||
@keydown.esc="editableValueKey = null"
|
||||
@pressEnter="updateConfigurationValue(configrecord)"
|
||||
@change="value => setConfigurationEditable(configrecord, value)"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</span>
|
||||
<span v-else-if="configrecord.type === 'Select'">
|
||||
<a-tooltip :title="editableValue">
|
||||
<a-select
|
||||
style="width: 20vw"
|
||||
:defaultValue="actualValue"
|
||||
:disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
|
||||
v-model:value="editableValue"
|
||||
@keydown.esc="editableValueKey = null"
|
||||
@pressEnter="updateConfigurationValue(configrecord)"
|
||||
@change="value => setConfigurationEditable(configrecord, value)">
|
||||
<a-select-option
|
||||
v-for="value of configrecord.options.split(',')"
|
||||
:key="value">
|
||||
{{ value }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span v-else-if="configrecord.type === 'Order'">
|
||||
<a-tooltip :title="editableValue.join(', ')">
|
||||
<b>{{ $t('message.select.deselect.to.sort') }}</b>
|
||||
<br />
|
||||
<a-select
|
||||
style="width: 20vw"
|
||||
mode="multiple"
|
||||
:defaultValue="actualValue"
|
||||
:disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
|
||||
v-model:value="editableValue"
|
||||
@keydown.esc="editableValueKey = null"
|
||||
@pressEnter="updateConfigurationValue(configrecord)"
|
||||
@change="value => setConfigurationEditable(configrecord, value)">
|
||||
<a-select-option
|
||||
v-for="value of configrecord.options.split(',')"
|
||||
:key="value">
|
||||
{{ value }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span v-else-if="configrecord.type === 'CSV'">
|
||||
<a-tooltip :title="editableValue.join(', ')">
|
||||
<b>{{ $t('message.type.values.to.add') }}</b>
|
||||
<br />
|
||||
<a-select
|
||||
style="width: 20vw"
|
||||
mode="tags"
|
||||
:disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
|
||||
v-model:value="editableValue"
|
||||
@keydown.esc="editableValueKey = null"
|
||||
@pressEnter="updateConfigurationValue(configrecord)"
|
||||
@change="value => setConfigurationEditable(configrecord, value)">
|
||||
</a-select>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span v-else>
|
||||
<a-tooltip :title="editableValue">
|
||||
<a-textarea
|
||||
style="width: 20vw; word-break: break-all"
|
||||
:defaultValue="actualValue"
|
||||
:disabled="(!('updateConfiguration' in $store.getters.apis) || configDisabled)"
|
||||
v-model:value="editableValue"
|
||||
@keydown.esc="editableValueKey = null"
|
||||
@pressEnter="updateConfigurationValue(configrecord)"
|
||||
@change="value => setConfigurationEditable(configrecord, value)"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span class="actions">
|
||||
<tooltip-button
|
||||
:tooltip="$t('label.cancel')"
|
||||
@onClick="cancelEditConfigurationValue(configrecord)"
|
||||
v-if="editableValueKey !== null"
|
||||
iconType="CloseCircleTwoTone"
|
||||
iconTwoToneColor="#f5222d"
|
||||
:disabled="valueLoading" />
|
||||
<tooltip-button
|
||||
:tooltip="$t('label.ok')"
|
||||
@onClick="updateConfigurationValue(configrecord)"
|
||||
v-if="editableValueKey !== null"
|
||||
iconType="CheckCircleTwoTone"
|
||||
iconTwoToneColor="#52c41a"
|
||||
:disabled="valueLoading" />
|
||||
<tooltip-button
|
||||
:tooltip="$t('label.reset.config.value')"
|
||||
@onClick="resetConfigurationValue(configrecord)"
|
||||
v-if="editableValueKey === null"
|
||||
icon="reload-outlined"
|
||||
:disabled="(!('resetConfiguration' in $store.getters.apis) || configDisabled || valueLoading)" />
|
||||
</span>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</template>
|
||||
<script>
|
||||
import { api } from '@/api'
|
||||
import TooltipButton from '@/components/widgets/TooltipButton'
|
||||
|
||||
export default {
|
||||
name: 'ConfigurationValue',
|
||||
components: {
|
||||
TooltipButton
|
||||
},
|
||||
props: {
|
||||
configrecord: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
configDisabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
actions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
valueLoading: this.loading,
|
||||
actualValue: null,
|
||||
editableValue: null,
|
||||
editableValueKey: null
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.setConfigData()
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
methods: {
|
||||
setConfigData () {
|
||||
this.valueLoading = false
|
||||
this.editableValue = this.getEditableValue(this.configrecord)
|
||||
this.actualValue = this.editableValue
|
||||
this.editableValueKey = null
|
||||
},
|
||||
updateConfigurationValue (configrecord) {
|
||||
this.valueLoading = true
|
||||
this.editableValueKey = null
|
||||
var newValue = this.editableValue
|
||||
if (configrecord.type === 'Range') {
|
||||
newValue = newValue / 100
|
||||
}
|
||||
if (['Order', 'CSV'].includes(configrecord.type)) {
|
||||
newValue = newValue.join(',')
|
||||
}
|
||||
const params = {
|
||||
name: configrecord.name,
|
||||
value: newValue
|
||||
}
|
||||
api('updateConfiguration', params).then(json => {
|
||||
this.editableValue = this.getEditableValue(json.updateconfigurationresponse.configuration)
|
||||
this.actualValue = this.editableValue
|
||||
this.$emit('change-config', { value: newValue })
|
||||
this.$store.dispatch('RefreshFeatures')
|
||||
this.$message.success(`${this.$t('message.setting.updated')} ${configrecord.name}`)
|
||||
if (json.updateconfigurationresponse &&
|
||||
json.updateconfigurationresponse.configuration &&
|
||||
!json.updateconfigurationresponse.configuration.isdynamic &&
|
||||
['Admin'].includes(this.$store.getters.userInfo.roletype)) {
|
||||
this.$notification.warning({
|
||||
message: this.$t('label.status'),
|
||||
description: this.$t('message.restart.mgmt.server')
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
this.editableValue = this.actualValue
|
||||
console.error(error)
|
||||
this.$message.error(this.$t('message.error.save.setting'))
|
||||
this.$notification.error({
|
||||
message: this.$t('label.error'),
|
||||
description: this.$t('message.error.save.setting')
|
||||
})
|
||||
}).finally(() => {
|
||||
this.valueLoading = false
|
||||
this.$emit('refresh')
|
||||
})
|
||||
},
|
||||
resetConfigurationValue (configrecord) {
|
||||
this.valueLoading = true
|
||||
this.editableValueKey = null
|
||||
api('resetConfiguration', {
|
||||
name: configrecord.name
|
||||
}).then(json => {
|
||||
this.editableValue = this.getEditableValue(json.resetconfigurationresponse.configuration)
|
||||
this.actualValue = this.editableValue
|
||||
var newValue = this.editableValue
|
||||
if (configrecord.type === 'Range') {
|
||||
newValue = newValue / 100
|
||||
}
|
||||
this.$emit('change-config', { value: newValue })
|
||||
this.$store.dispatch('RefreshFeatures')
|
||||
this.$message.success(`${this.$t('label.setting')} ${configrecord.name} ${this.$t('label.reset.config.value')}`)
|
||||
if (json.resetconfigurationresponse &&
|
||||
json.resetconfigurationresponse.configuration &&
|
||||
!json.resetconfigurationresponse.configuration.isdynamic &&
|
||||
['Admin'].includes(this.$store.getters.userInfo.roletype)) {
|
||||
this.$notification.warning({
|
||||
message: this.$t('label.status'),
|
||||
description: this.$t('message.restart.mgmt.server')
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
this.editableValue = this.actualValue
|
||||
console.error(error)
|
||||
this.$message.error(this.$t('message.error.reset.config'))
|
||||
this.$notification.error({
|
||||
message: this.$t('label.error'),
|
||||
description: this.$t('message.error.reset.config')
|
||||
})
|
||||
}).finally(() => {
|
||||
this.valueLoading = false
|
||||
this.$emit('refresh')
|
||||
})
|
||||
},
|
||||
getEditableValue (configrecord) {
|
||||
if (configrecord.type === 'Range') {
|
||||
return Number(configrecord.value) * 100 || 0
|
||||
}
|
||||
if (configrecord.type === 'Boolean') {
|
||||
return configrecord.value === 'true'
|
||||
}
|
||||
if (configrecord.type === 'Number' || configrecord.type === 'Decimal') {
|
||||
if (configrecord.value) {
|
||||
return Number(configrecord.value)
|
||||
} else if (configrecord.defaultvalue) {
|
||||
return Number(configrecord.defaultvalue)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
if (['Order', 'CSV'].includes(configrecord.type)) {
|
||||
if (configrecord.value && configrecord.value.length > 0) {
|
||||
return String(configrecord.value).split(',')
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
if (configrecord.value) {
|
||||
return String(configrecord.value)
|
||||
}
|
||||
if (configrecord.defaultvalue) {
|
||||
return String(configrecord.defaultvalue)
|
||||
}
|
||||
return ''
|
||||
},
|
||||
cancelEditConfigurationValue (configrecord) {
|
||||
this.editableValueKey = null
|
||||
this.editableValue = this.getEditableValue(configrecord)
|
||||
},
|
||||
setConfigurationEditable (configrecord, value) {
|
||||
if (this.actualValue !== this.editableValue) {
|
||||
this.editableValueKey = 'edit'
|
||||
} else {
|
||||
this.editableValueKey = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.actions {
|
||||
margin-left: 10px;
|
||||
width: 100px;
|
||||
}
|
||||
</style>
|
||||
@ -30,6 +30,8 @@ import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl;
|
||||
import org.apache.cloudstack.test.utils.SpringUtils;
|
||||
|
||||
import com.cloud.alert.AlertManager;
|
||||
@ -66,7 +68,7 @@ import com.cloud.user.dao.UserStatisticsDaoImpl;
|
||||
@ComponentScan(basePackageClasses = {AccountDaoImpl.class, UsageDaoImpl.class, UsageJobDaoImpl.class, UsageVMInstanceDaoImpl.class, UsageIPAddressDaoImpl.class,
|
||||
UsageNetworkDaoImpl.class, UsageVolumeDaoImpl.class, UsageStorageDaoImpl.class, UsageLoadBalancerPolicyDaoImpl.class,
|
||||
UsagePortForwardingRuleDaoImpl.class, UsageNetworkOfferingDaoImpl.class, UsageVPNUserDaoImpl.class, UsageVmDiskDaoImpl.class,
|
||||
UsageSecurityGroupDaoImpl.class, ConfigurationDaoImpl.class, UsageManagerImpl.class, VMInstanceUsageParser.class, IPAddressUsageParser.class,
|
||||
UsageSecurityGroupDaoImpl.class, ConfigurationDaoImpl.class, ConfigurationGroupDaoImpl.class, ConfigurationSubGroupDaoImpl.class, UsageManagerImpl.class, VMInstanceUsageParser.class, IPAddressUsageParser.class,
|
||||
LoadBalancerUsageParser.class, NetworkOfferingUsageParser.class, NetworkUsageParser.class, PortForwardingUsageParser.class,
|
||||
SecurityGroupUsageParser.class, StorageUsageParser.class, VmDiskUsageParser.class, VolumeUsageParser.class, VPNUserUsageParser.class,
|
||||
UserStatisticsDaoImpl.class},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user