mirror of https://github.com/apache/cloudstack.git
[Quota] Add API to list preset variables (#8372)
* Add API for listing Quota preset variables * Add new line at EOF * Address review * Remove usage types * Remove usage types from quotatypes * Remove unused imports * Add space for preset variable definition description Co-authored-by: Bernardo De Marco Gonçalves <bernardomg2004@gmail.com> --------- Co-authored-by: Bernardo De Marco Gonçalves <bernardomg2004@gmail.com>
This commit is contained in:
parent
cb48202b34
commit
1cf1786ebb
|
|
@ -17,7 +17,9 @@
|
|||
|
||||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
public class Account extends GenericPresetVariable{
|
||||
public class Account extends GenericPresetVariable {
|
||||
@PresetVariableDefinition(description = "Role of the account. This field will not exist if the account is a project.")
|
||||
|
||||
private Role role;
|
||||
|
||||
public Role getRole() {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
public class BackupOffering extends GenericPresetVariable {
|
||||
@PresetVariableDefinition(description = "External ID of the backup offering that generated the backup.")
|
||||
private String externalId;
|
||||
|
||||
public String getExternalId() {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
public class ComputeOffering extends GenericPresetVariable {
|
||||
@PresetVariableDefinition(description = "A boolean informing if the compute offering is customized or not.")
|
||||
private boolean customized;
|
||||
|
||||
public boolean isCustomized() {
|
||||
|
|
|
|||
|
|
@ -21,8 +21,13 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
|
|||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
public class ComputingResources {
|
||||
@PresetVariableDefinition(description = "Current VM's memory (in MiB).")
|
||||
private Integer memory;
|
||||
|
||||
@PresetVariableDefinition(description = "Current VM's vCPUs.")
|
||||
private Integer cpuNumber;
|
||||
|
||||
@PresetVariableDefinition(description = "Current VM's CPU speed (in MHz).")
|
||||
private Integer cpuSpeed;
|
||||
|
||||
public Integer getMemory() {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.cloudstack.quota.activationrule.presetvariables;
|
||||
|
||||
public class Domain extends GenericPresetVariable {
|
||||
@PresetVariableDefinition(description = "Path of the domain owner of the resource.")
|
||||
private String path;
|
||||
|
||||
public String getPath() {
|
||||
|
|
|
|||
|
|
@ -23,8 +23,12 @@ import java.util.Set;
|
|||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
|
||||
public class GenericPresetVariable {
|
||||
@PresetVariableDefinition(description = "ID of the resource.")
|
||||
private String id;
|
||||
|
||||
@PresetVariableDefinition(description = "Name of the resource.")
|
||||
private String name;
|
||||
|
||||
protected transient Set<String> fieldNamesToIncludeInToString = new HashSet<>();
|
||||
|
||||
public String getId() {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@ package org.apache.cloudstack.quota.activationrule.presetvariables;
|
|||
import java.util.List;
|
||||
|
||||
public class Host extends GenericPresetVariable {
|
||||
@PresetVariableDefinition(description = "List of tags of the host where the VM is running (i.e.: [\"a\", \"b\"]).")
|
||||
private List<String> tags;
|
||||
|
||||
@PresetVariableDefinition(description = "Whether the tag is a rule interpreted in JavaScript.")
|
||||
private Boolean isTagARule;
|
||||
|
||||
public List<String> getTags() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
// 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
|
||||
// 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.quota.activationrule.presetvariables;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Describes the preset variable and indicates to which Quota usage types it is loaded.
|
||||
*/
|
||||
@Target(FIELD)
|
||||
@Retention(RUNTIME)
|
||||
public @interface PresetVariableDefinition {
|
||||
/**
|
||||
* An array indicating for which Quota usage types the preset variable is loaded.
|
||||
* @return an array with the usage types for which the preset variable is loaded.
|
||||
*/
|
||||
int[] supportedTypes() default 0;
|
||||
|
||||
/**
|
||||
* A {@link String} describing the preset variable.
|
||||
* @return the description of the preset variable.
|
||||
*/
|
||||
String description() default "";
|
||||
}
|
||||
|
|
@ -19,11 +19,22 @@ package org.apache.cloudstack.quota.activationrule.presetvariables;
|
|||
|
||||
public class PresetVariables {
|
||||
|
||||
@PresetVariableDefinition(description = "Account owner of the resource.")
|
||||
private Account account;
|
||||
|
||||
@PresetVariableDefinition(description = "Domain owner of the resource.")
|
||||
private Domain domain;
|
||||
|
||||
@PresetVariableDefinition(description = "Project owner of the resource. This field will not exist if the resource belongs to an account.")
|
||||
private GenericPresetVariable project;
|
||||
|
||||
@PresetVariableDefinition(description = "Type of the record used. Examples for this are: VirtualMachine, DomainRouter, SourceNat, KVM.")
|
||||
private String resourceType;
|
||||
|
||||
@PresetVariableDefinition(description = "Data related to the resource being processed.")
|
||||
private Value value;
|
||||
|
||||
@PresetVariableDefinition(description = "Zone where the resource is.")
|
||||
private GenericPresetVariable zone;
|
||||
|
||||
public Account getAccount() {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.apache.cloudstack.quota.activationrule.presetvariables;
|
|||
import org.apache.cloudstack.acl.RoleType;
|
||||
|
||||
public class Role extends GenericPresetVariable {
|
||||
@PresetVariableDefinition(description = "Role type of the resource's owner.")
|
||||
private RoleType type;
|
||||
|
||||
public RoleType getType() {
|
||||
|
|
|
|||
|
|
@ -22,9 +22,13 @@ import java.util.List;
|
|||
import com.cloud.storage.ScopeType;
|
||||
|
||||
public class Storage extends GenericPresetVariable {
|
||||
@PresetVariableDefinition(description = "List of string representing the tags of the storage where the volume is (i.e.: [\"a\", \"b\"]).")
|
||||
private List<String> tags;
|
||||
|
||||
@PresetVariableDefinition(description = "Whether the tag is a rule interpreted in JavaScript. Applicable only for primary storages.")
|
||||
private Boolean isTagARule;
|
||||
|
||||
@PresetVariableDefinition(description = "Scope of the storage where the volume is. Values can be: ZONE, CLUSTER or HOST. Applicable only for primary storages.")
|
||||
private ScopeType scope;
|
||||
|
||||
public List<String> getTags() {
|
||||
|
|
|
|||
|
|
@ -23,25 +23,75 @@ import java.util.Map;
|
|||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.Storage.ProvisioningType;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
|
||||
public class Value extends GenericPresetVariable {
|
||||
|
||||
@PresetVariableDefinition(description = "ID of the resource.", supportedTypes = {QuotaTypes.ALLOCATED_VM, QuotaTypes.RUNNING_VM, QuotaTypes.VOLUME, QuotaTypes.TEMPLATE,
|
||||
QuotaTypes.ISO, QuotaTypes.SNAPSHOT, QuotaTypes.NETWORK_OFFERING, QuotaTypes.VM_SNAPSHOT})
|
||||
private String id;
|
||||
|
||||
@PresetVariableDefinition(description = "Name of the resource.", supportedTypes = {QuotaTypes.ALLOCATED_VM, QuotaTypes.RUNNING_VM, QuotaTypes.VOLUME, QuotaTypes.TEMPLATE,
|
||||
QuotaTypes.ISO, QuotaTypes.SNAPSHOT, QuotaTypes.NETWORK_OFFERING, QuotaTypes.VM_SNAPSHOT})
|
||||
private String name;
|
||||
|
||||
@PresetVariableDefinition(description = "Host where the VM is running.", supportedTypes = {QuotaTypes.RUNNING_VM})
|
||||
private Host host;
|
||||
|
||||
@PresetVariableDefinition(description = "OS of the VM/template.", supportedTypes = {QuotaTypes.RUNNING_VM, QuotaTypes.ALLOCATED_VM, QuotaTypes.TEMPLATE, QuotaTypes.ISO})
|
||||
private String osName;
|
||||
|
||||
@PresetVariableDefinition(description = "A list of resources of the account between the start and end date of the usage record being calculated " +
|
||||
"(i.e.: [{zoneId: ..., domainId:...}]).")
|
||||
private List<Resource> accountResources;
|
||||
|
||||
@PresetVariableDefinition(supportedTypes = {QuotaTypes.ALLOCATED_VM, QuotaTypes.RUNNING_VM, QuotaTypes.VOLUME, QuotaTypes.TEMPLATE, QuotaTypes.ISO, QuotaTypes.SNAPSHOT,
|
||||
QuotaTypes.VM_SNAPSHOT}, description = "List of tags of the resource in the format key:value (i.e.: {\"a\":\"b\", \"c\":\"d\"}).")
|
||||
private Map<String, String> tags;
|
||||
|
||||
@PresetVariableDefinition(description = "Tag of the network offering.", supportedTypes = {QuotaTypes.NETWORK_OFFERING})
|
||||
private String tag;
|
||||
|
||||
@PresetVariableDefinition(description = "Size of the resource (in MiB).", supportedTypes = {QuotaTypes.TEMPLATE, QuotaTypes.ISO, QuotaTypes.VOLUME, QuotaTypes.SNAPSHOT,
|
||||
QuotaTypes.BACKUP})
|
||||
private Long size;
|
||||
|
||||
@PresetVariableDefinition(description = "Virtual size of the backup.", supportedTypes = {QuotaTypes.BACKUP})
|
||||
private Long virtualSize;
|
||||
|
||||
@PresetVariableDefinition(description = "Provisioning type of the resource. Values can be: thin, sparse or fat.", supportedTypes = {QuotaTypes.VOLUME})
|
||||
private ProvisioningType provisioningType;
|
||||
|
||||
@PresetVariableDefinition(description = "Type of the snapshot. Values can be: MANUAL, RECURRING, HOURLY, DAILY, WEEKLY and MONTHLY.", supportedTypes = {QuotaTypes.SNAPSHOT})
|
||||
private Snapshot.Type snapshotType;
|
||||
|
||||
@PresetVariableDefinition(description = "Type of the VM snapshot. Values can be: Disk or DiskAndMemory.", supportedTypes = {QuotaTypes.VM_SNAPSHOT})
|
||||
private VMSnapshot.Type vmSnapshotType;
|
||||
|
||||
@PresetVariableDefinition(description = "Computing offering of the VM.", supportedTypes = {QuotaTypes.RUNNING_VM, QuotaTypes.ALLOCATED_VM})
|
||||
private ComputeOffering computeOffering;
|
||||
|
||||
@PresetVariableDefinition(description = "Template/ISO with which the VM was created.", supportedTypes = {QuotaTypes.RUNNING_VM, QuotaTypes.ALLOCATED_VM})
|
||||
private GenericPresetVariable template;
|
||||
|
||||
@PresetVariableDefinition(description = "Disk offering of the volume.", supportedTypes = {QuotaTypes.VOLUME})
|
||||
private GenericPresetVariable diskOffering;
|
||||
|
||||
@PresetVariableDefinition(description = "Storage where the volume or snapshot is. While handling with snapshots, this value can be from the primary storage if the global " +
|
||||
"setting 'snapshot.backup.to.secondary' is false, otherwise it will be from secondary storage.", supportedTypes = {QuotaTypes.VOLUME, QuotaTypes.SNAPSHOT})
|
||||
private Storage storage;
|
||||
|
||||
@PresetVariableDefinition(description = "Computing resources consumed by the VM.", supportedTypes = {QuotaTypes.RUNNING_VM})
|
||||
private ComputingResources computingResources;
|
||||
|
||||
@PresetVariableDefinition(description = "Backup offering of the backup.", supportedTypes = {QuotaTypes.BACKUP})
|
||||
private BackupOffering backupOffering;
|
||||
|
||||
@PresetVariableDefinition(description = "The hypervisor where the resource was deployed. Values can be: XenServer, KVM, VMware, Hyperv, BareMetal, Ovm, Ovm3 and LXC.",
|
||||
supportedTypes = {QuotaTypes.RUNNING_VM, QuotaTypes.ALLOCATED_VM, QuotaTypes.VM_SNAPSHOT, QuotaTypes.SNAPSHOT})
|
||||
private String hypervisorType;
|
||||
|
||||
@PresetVariableDefinition(description = "The volume format. Values can be: RAW, VHD, VHDX, OVA and QCOW2.", supportedTypes = {QuotaTypes.VOLUME, QuotaTypes.VOLUME_SECONDARY})
|
||||
private String volumeFormat;
|
||||
private String state;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import java.util.Map;
|
|||
|
||||
import org.apache.cloudstack.usage.UsageTypes;
|
||||
import org.apache.cloudstack.usage.UsageUnitTypes;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
|
||||
public class QuotaTypes extends UsageTypes {
|
||||
private final Integer quotaType;
|
||||
|
|
@ -100,4 +101,13 @@ public class QuotaTypes extends UsageTypes {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static public QuotaTypes getQuotaType(int quotaType) {
|
||||
return quotaTypeMap.get(quotaType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "quotaType", "quotaName");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,20 @@ import org.mockito.junit.MockitoJUnitRunner;
|
|||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ValueTest {
|
||||
|
||||
@Test
|
||||
public void setIdTestAddFieldIdToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setId(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setNameTestAddFieldNameToCollection() {
|
||||
Value variable = new Value();
|
||||
variable.setName(null);
|
||||
Assert.assertTrue(variable.fieldNamesToIncludeInToString.contains("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setHostTestAddFieldHostToCollection() {
|
||||
Value variable = new Value();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
//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;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaPresetVariablesItemResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
@APICommand(name = "quotaPresetVariablesList", responseObject = QuotaPresetVariablesItemResponse.class, description = "List the preset variables available for using in the " +
|
||||
"Quota tariff activation rules given the usage type.", since = "4.20", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaPresetVariablesListCmd extends BaseCmd {
|
||||
|
||||
@Inject
|
||||
QuotaResponseBuilder quotaResponseBuilder;
|
||||
|
||||
@Parameter(name = ApiConstants.USAGE_TYPE, type = CommandType.INTEGER, required = true, description = "The usage type for which the preset variables will be retrieved.")
|
||||
private Integer quotaType;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
List<QuotaPresetVariablesItemResponse> responses = quotaResponseBuilder.listQuotaPresetVariables(this);
|
||||
ListResponse<QuotaPresetVariablesItemResponse> listResponse = new ListResponse<>();
|
||||
listResponse.setResponses(responses);
|
||||
listResponse.setResponseName(getCommandName());
|
||||
setResponseObject(listResponse);
|
||||
}
|
||||
|
||||
public QuotaTypes getQuotaType() {
|
||||
QuotaTypes quotaTypes = QuotaTypes.getQuotaType(quotaType);
|
||||
|
||||
if (quotaTypes == null) {
|
||||
throw new InvalidParameterValueException(String.format("Usage type not found for value [%s].", quotaType));
|
||||
}
|
||||
|
||||
return quotaTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
//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.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
public class QuotaPresetVariablesItemResponse extends BaseResponse {
|
||||
@SerializedName("variable")
|
||||
@Param(description = "variable")
|
||||
private String variable;
|
||||
|
||||
@SerializedName("description")
|
||||
@Param(description = "description")
|
||||
private String description;
|
||||
|
||||
public QuotaPresetVariablesItemResponse() {
|
||||
super("variables");
|
||||
}
|
||||
|
||||
public void setVariable(String variable) {
|
||||
this.variable = variable;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import org.apache.cloudstack.api.command.QuotaBalanceCmd;
|
|||
import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaPresetVariablesListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffCreateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
|
|
@ -72,6 +73,13 @@ public interface QuotaResponseBuilder {
|
|||
|
||||
boolean deleteQuotaTariff(String quotaTariffUuid);
|
||||
|
||||
/**
|
||||
* Lists the preset variables for the usage type informed in the command.
|
||||
* @param cmd used to retrieve the Quota usage type parameter.
|
||||
* @return the response consisting of a {@link List} of the preset variables and their descriptions.
|
||||
*/
|
||||
List<QuotaPresetVariablesItemResponse> listQuotaPresetVariables(QuotaPresetVariablesListCmd cmd);
|
||||
|
||||
Pair<QuotaEmailConfigurationVO, Double> configureQuotaEmail(QuotaConfigureEmailCmd cmd);
|
||||
|
||||
QuotaConfigureEmailResponse createQuotaConfigureEmailResponse(QuotaEmailConfigurationVO quotaEmailConfigurationVO, Double minBalance, long accountId);
|
||||
|
|
|
|||
|
|
@ -16,11 +16,15 @@
|
|||
//under the License.
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
|
@ -31,6 +35,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
|
@ -41,6 +46,7 @@ import org.apache.cloudstack.api.command.QuotaBalanceCmd;
|
|||
import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaPresetVariablesListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffCreateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
|
|
@ -50,6 +56,11 @@ import org.apache.cloudstack.quota.QuotaManager;
|
|||
import org.apache.cloudstack.quota.QuotaManagerImpl;
|
||||
import org.apache.cloudstack.quota.QuotaService;
|
||||
import org.apache.cloudstack.quota.QuotaStatement;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.ComputingResources;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.GenericPresetVariable;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableDefinition;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.Value;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
|
|
@ -67,6 +78,8 @@ import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
|||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
|
@ -119,6 +132,8 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
@Inject
|
||||
private QuotaEmailConfigurationDao quotaEmailConfigurationDao;
|
||||
|
||||
private final Class<?>[] assignableClasses = {GenericPresetVariable.class, ComputingResources.class};
|
||||
|
||||
@Override
|
||||
public QuotaTariffResponse createQuotaTariffResponse(QuotaTariffVO tariff) {
|
||||
final QuotaTariffResponse response = new QuotaTariffResponse();
|
||||
|
|
@ -680,6 +695,119 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
return _quotaTariffDao.updateQuotaTariff(quotaTariff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaPresetVariablesItemResponse> listQuotaPresetVariables(QuotaPresetVariablesListCmd cmd) {
|
||||
List<QuotaPresetVariablesItemResponse> response;
|
||||
List<Pair<String, String>> variables = new ArrayList<>();
|
||||
|
||||
QuotaTypes quotaType = cmd.getQuotaType();
|
||||
addAllPresetVariables(PresetVariables.class, quotaType, variables, null);
|
||||
response = createQuotaPresetVariablesResponse(variables);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all preset variables for the given quota type. It recursively finds all presets variables for the given {@link Class} and puts it in a {@link List}. Each item in the
|
||||
* list is a {@link Pair} that consists of the variable name and its description.
|
||||
*
|
||||
* @param clazz used to find the non-transient fields. If it is equal to the {@link Value} class, then it only gets the declared fields, otherwise, it gets all fields,
|
||||
* including its parent's fields.
|
||||
* @param quotaType used to check if the field supports the quota resource type. It uses the annotation method {@link PresetVariableDefinition#supportedTypes()} for this
|
||||
* verification.
|
||||
* @param variables the {@link List} which contains the {@link Pair} of the preset variable and its description.
|
||||
* @param recursiveVariableName {@link String} used for recursively building the preset variable string.
|
||||
*/
|
||||
public void addAllPresetVariables(Class<?> clazz, QuotaTypes quotaType, List<Pair<String, String>> variables, String recursiveVariableName) {
|
||||
Field[] allFields = Value.class.equals(clazz) ? clazz.getDeclaredFields() : FieldUtils.getAllFields(clazz);
|
||||
List<Field> fieldsNonTransients = Arrays.stream(allFields).filter(field -> !Modifier.isTransient(field.getModifiers())).collect(Collectors.toList());
|
||||
for (Field field : fieldsNonTransients) {
|
||||
PresetVariableDefinition presetVariableDefinitionAnnotation = field.getAnnotation(PresetVariableDefinition.class);
|
||||
Class<?> fieldClass = getClassOfField(field);
|
||||
String presetVariableName = field.getName();
|
||||
|
||||
if (presetVariableDefinitionAnnotation == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(recursiveVariableName)) {
|
||||
presetVariableName = String.format("%s.%s", recursiveVariableName, field.getName());
|
||||
}
|
||||
filterSupportedTypes(variables, quotaType, presetVariableDefinitionAnnotation, fieldClass, presetVariableName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class of the {@link Field} depending on its type. This method is required for retrieving the Class of Generic Types, i.e. {@link List}.
|
||||
*/
|
||||
protected Class<?> getClassOfField(Field field){
|
||||
if (field.getGenericType() instanceof ParameterizedType) {
|
||||
ParameterizedType genericType = (ParameterizedType) field.getGenericType();
|
||||
return (Class<?>) genericType.getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
return field.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the {@link PresetVariableDefinition} supports the given {@link QuotaTypes}. If it supports it, it adds the preset variable to the {@link List} recursively
|
||||
* if it is from the one of the classes in the {@link QuotaResponseBuilderImpl#assignableClasses} array or directly if not.
|
||||
*
|
||||
* @param variables {@link List} of the {@link Pair} of the preset variable and its description.
|
||||
* @param quotaType the given {@link QuotaTypes} to filter.
|
||||
* @param presetVariableDefinitionAnnotation used to check if the quotaType is supported.
|
||||
* @param fieldClass class of the field used to verify if it is from the {@link GenericPresetVariable} or {@link ComputingResources} classes. If it is, then it calls
|
||||
* {@link QuotaResponseBuilderImpl#addAllPresetVariables(Class, QuotaTypes, List, String)} to add the preset variable. Otherwise, the {@link Pair} is
|
||||
* added directly to the variables {@link List}.
|
||||
* @param presetVariableName {@link String} that contains the recursive created preset variable name.
|
||||
*/
|
||||
public void filterSupportedTypes(List<Pair<String, String>> variables, QuotaTypes quotaType, PresetVariableDefinition presetVariableDefinitionAnnotation, Class<?> fieldClass,
|
||||
String presetVariableName) {
|
||||
if (Arrays.stream(presetVariableDefinitionAnnotation.supportedTypes()).noneMatch(supportedType ->
|
||||
supportedType == quotaType.getQuotaType() || supportedType == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String presetVariableDescription = presetVariableDefinitionAnnotation.description();
|
||||
|
||||
Pair<String, String> pair = new Pair<>(presetVariableName, presetVariableDescription);
|
||||
variables.add(pair);
|
||||
|
||||
if (isRecursivePresetVariable(fieldClass)) {
|
||||
addAllPresetVariables(fieldClass, quotaType, variables, presetVariableName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the {@link Class} of the {@link Field} is from one of the classes in the array {@link QuotaResponseBuilderImpl#assignableClasses}, i.e., it is a recursive
|
||||
* {@link PresetVariables}, returns false otherwise.
|
||||
*/
|
||||
private boolean isRecursivePresetVariable(Class<?> fieldClass) {
|
||||
for (Class<?> clazz : assignableClasses) {
|
||||
if (clazz.isAssignableFrom(fieldClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<QuotaPresetVariablesItemResponse> createQuotaPresetVariablesResponse(List<Pair<String, String>> variables) {
|
||||
final List<QuotaPresetVariablesItemResponse> responses = new ArrayList<>();
|
||||
|
||||
for (Pair<String, String> variable : variables) {
|
||||
responses.add(createPresetVariablesItemResponse(variable));
|
||||
}
|
||||
|
||||
return responses;
|
||||
}
|
||||
|
||||
public QuotaPresetVariablesItemResponse createPresetVariablesItemResponse(Pair<String, String> variable) {
|
||||
QuotaPresetVariablesItemResponse response = new QuotaPresetVariablesItemResponse();
|
||||
response.setVariable(variable.first());
|
||||
response.setDescription(variable.second());
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<QuotaEmailConfigurationVO, Double> configureQuotaEmail(QuotaConfigureEmailCmd cmd) {
|
||||
validateQuotaConfigureEmailCmdParameters(cmd);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
|||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEnabledCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaListEmailConfigurationCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaPresetVariablesListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaSummaryCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffCreateCmd;
|
||||
|
|
@ -119,6 +120,7 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
|||
cmdList.add(QuotaTariffDeleteCmd.class);
|
||||
cmdList.add(QuotaConfigureEmailCmd.class);
|
||||
cmdList.add(QuotaListEmailConfigurationCmd.class);
|
||||
cmdList.add(QuotaPresetVariablesListCmd.class);
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import java.util.function.Consumer;
|
|||
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.utils.Pair;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
|
|
@ -36,6 +37,9 @@ import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
|||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.quota.QuotaService;
|
||||
import org.apache.cloudstack.quota.QuotaStatement;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableDefinition;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.Value;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
|
|
@ -419,6 +423,46 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
|||
assertTrue(quotaSummaryResponse.getQuotaEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterSupportedTypesTestReturnWhenQuotaTypeDoesNotMatch() throws NoSuchFieldException {
|
||||
List<Pair<String, String>> variables = new ArrayList<>();
|
||||
Class<?> clazz = Value.class;
|
||||
PresetVariableDefinition presetVariableDefinitionAnnotation = clazz.getDeclaredField("host").getAnnotation(PresetVariableDefinition.class);
|
||||
QuotaTypes quotaType = QuotaTypes.getQuotaType(QuotaTypes.NETWORK_OFFERING);
|
||||
int expectedVariablesSize = 0;
|
||||
|
||||
quotaResponseBuilderSpy.filterSupportedTypes(variables, quotaType, presetVariableDefinitionAnnotation, clazz, null);
|
||||
|
||||
assertEquals(expectedVariablesSize, variables.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterSupportedTypesTestAddPresetVariableWhenClassIsNotInstanceOfGenericPresetVariableAndComputingResource() throws NoSuchFieldException {
|
||||
List<Pair<String, String>> variables = new ArrayList<>();
|
||||
Class<?> clazz = PresetVariables.class;
|
||||
PresetVariableDefinition presetVariableDefinitionAnnotation = clazz.getDeclaredField("resourceType").getAnnotation(PresetVariableDefinition.class);
|
||||
QuotaTypes quotaType = QuotaTypes.getQuotaType(QuotaTypes.NETWORK_OFFERING);
|
||||
int expectedVariablesSize = 1;
|
||||
String expectedVariableName = "variable.name";
|
||||
|
||||
quotaResponseBuilderSpy.filterSupportedTypes(variables, quotaType, presetVariableDefinitionAnnotation, clazz, "variable.name");
|
||||
|
||||
assertEquals(expectedVariablesSize, variables.size());
|
||||
assertEquals(expectedVariableName, variables.get(0).first());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterSupportedTypesTestCallRecursiveMethodWhenIsGenericPresetVariableClassOrComputingResourceClass() throws NoSuchFieldException {
|
||||
List<Pair<String, String>> variables = new ArrayList<>();
|
||||
Class<?> clazz = Value.class;
|
||||
PresetVariableDefinition presetVariableDefinitionAnnotation = clazz.getDeclaredField("storage").getAnnotation(PresetVariableDefinition.class);
|
||||
QuotaTypes quotaType = QuotaTypes.getQuotaType(QuotaTypes.VOLUME);
|
||||
|
||||
quotaResponseBuilderSpy.filterSupportedTypes(variables, quotaType, presetVariableDefinitionAnnotation, clazz, "variable.name");
|
||||
|
||||
Mockito.verify(quotaResponseBuilderSpy, Mockito.atLeastOnce()).addAllPresetVariables(Mockito.any(), Mockito.any(QuotaTypes.class), Mockito.anyList(),
|
||||
Mockito.anyString());
|
||||
}
|
||||
|
||||
@Test (expected = InvalidParameterValueException.class)
|
||||
public void validateQuotaConfigureEmailCmdParametersTestNullQuotaAccount() {
|
||||
|
|
@ -442,7 +486,6 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
|||
quotaResponseBuilderSpy.validateQuotaConfigureEmailCmdParameters(quotaConfigureEmailCmdMock);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void validateQuotaConfigureEmailCmdParametersTestNullTemplateName() {
|
||||
Mockito.doReturn(quotaAccountVOMock).when(quotaAccountDaoMock).findByIdQuotaAccount(Mockito.any());
|
||||
|
|
|
|||
Loading…
Reference in New Issue