Merge branch 'main' into nsx-integration

This commit is contained in:
nvazquez 2024-02-19 08:24:37 -03:00
commit 4c36d56143
No known key found for this signature in database
GPG Key ID: 656E1BCC8CB54F84
139 changed files with 6856 additions and 1281 deletions

View File

@ -179,7 +179,8 @@ jobs:
"component/test_project_usage
component/test_protocol_number_security_group
component/test_public_ip
component/test_resource_limits",
component/test_resource_limits
component/test_resource_limit_tags",
"component/test_regions_accounts
component/test_routers
component/test_snapshots

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.capacity;
import java.util.List;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@ -35,6 +37,11 @@ public interface Capacity extends InternalIdentity, Identity {
public static final short CAPACITY_TYPE_CPU_CORE = 90;
public static final List<Short> STORAGE_CAPACITY_TYPES = List.of(CAPACITY_TYPE_STORAGE,
CAPACITY_TYPE_STORAGE_ALLOCATED,
CAPACITY_TYPE_SECONDARY_STORAGE,
CAPACITY_TYPE_LOCAL_STORAGE);
public Long getHostOrPoolId();
public Long getDataCenterId();
@ -54,4 +61,6 @@ public interface Capacity extends InternalIdentity, Identity {
public Float getUsedPercentage();
public Long getAllocatedCapacity();
public String getTag();
}

View File

@ -85,5 +85,6 @@ public interface Resource {
long getOwnerId();
ResourceOwnerType getResourceOwnerType();
String getTag();
}

View File

@ -449,10 +449,11 @@ public interface ManagementService {
* this method removes the child storage pools and adds the corresponding parent datastore cluster for API response listing
*
* @param Long volumeId
* @param String keyword if passed, will only return storage pools that contain this keyword in the name
* @return Pair<List<? extends StoragePool>, List<? extends StoragePool>> List of storage pools in cluster and list
* of pools with enough capacity.
*/
Pair<List<? extends StoragePool>, List<? extends StoragePool>> listStoragePoolsForMigrationOfVolume(Long volumeId);
Pair<List<? extends StoragePool>, List<? extends StoragePool>> listStoragePoolsForMigrationOfVolume(Long volumeId, String keyword);
Pair<List<? extends StoragePool>, List<? extends StoragePool>> listStoragePoolsForSystemMigrationOfVolume(Long volumeId, Long newDiskOfferingId, Long newSize, Long newMinIops, Long newMaxIops, boolean keepSourceStoragePool, boolean bypassStorageTypeCheck);

View File

@ -30,6 +30,8 @@ import com.cloud.utils.fsm.StateObject;
public interface Volume extends ControlledEntity, Identity, InternalIdentity, BasedOn, StateObject<Volume.State>, Displayable {
static final long DISK_OFFERING_SUITABILITY_CHECK_VOLUME_ID = -1;
// Managed storage volume parameters (specified in the compute/disk offering for PowerFlex)
String BANDWIDTH_LIMIT_IN_MBPS = "bandwidthLimitInMbps";
String IOPS_LIMIT = "iopsLimit";

View File

@ -18,13 +18,18 @@ package com.cloud.user;
import java.util.List;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.ResourceCount;
import com.cloud.configuration.ResourceLimit;
import com.cloud.domain.Domain;
import com.cloud.exception.ResourceAllocationException;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.user.ResourceReservation;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.template.VirtualMachineTemplate;
public interface ResourceLimitService {
@ -34,6 +39,13 @@ public interface ResourceLimitService {
"The default maximum secondary storage space (in GiB) that can be used for a project", false);
static final ConfigKey<Long> ResourceCountCheckInterval = new ConfigKey<>("Advanced", Long.class, "resourcecount.check.interval", "300",
"Time (in seconds) to wait before running resource recalculation and fixing task. Default is 300 seconds, Setting this to 0 disables execution of the task", false);
static final ConfigKey<String> ResourceLimitHostTags = new ConfigKey<>("Advanced", String.class, "resource.limit.host.tags", "",
"A comma-separated list of tags for host resource limits", true);
static final ConfigKey<String> ResourceLimitStorageTags = new ConfigKey<>("Advanced", String.class, "resource.limit.storage.tags", "",
"A comma-separated list of tags for storage resource limits", true);
static final List<ResourceType> HostTagsSupportingTypes = List.of(ResourceType.user_vm, ResourceType.cpu, ResourceType.memory);
static final List<ResourceType> StorageTagsSupportingTypes = List.of(ResourceType.volume, ResourceType.primary_storage);
/**
* Updates an existing resource limit with the specified details. If a limit doesn't exist, will create one.
@ -46,22 +58,27 @@ public interface ResourceLimitService {
* TODO
* @param max
* TODO
* @param tag
* tag for the resource type
*
* @return the updated/created resource limit
*/
ResourceLimit updateResourceLimit(Long accountId, Long domainId, Integer resourceType, Long max);
ResourceLimit updateResourceLimit(Long accountId, Long domainId, Integer resourceType, Long max, String tag);
/**
* Updates an existing resource count details for the account/domain
*
* @param accountId
* TODO
* Id of the account for which resource recalculation to be done
* @param domainId
* TODO
* Id of the domain for which resource recalculation to be doneDO
* @param typeId
* TODO
* type of the resource for which recalculation to be done
* @param tag
* tag for the resource type for which recalculation to be done
* @return the updated/created resource counts
*/
List<? extends ResourceCount> recalculateResourceCount(Long accountId, Long domainId, Integer typeId, String tag);
List<? extends ResourceCount> recalculateResourceCount(Long accountId, Long domainId, Integer typeId);
/**
@ -77,7 +94,7 @@ public interface ResourceLimitService {
* TODO
* @return a list of limits that match the criteria
*/
public List<? extends ResourceLimit> searchForLimits(Long id, Long accountId, Long domainId, ResourceType resourceType, Long startIndex, Long pageSizeVal);
public List<? extends ResourceLimit> searchForLimits(Long id, Long accountId, Long domainId, ResourceType resourceType, String tag, Long startIndex, Long pageSizeVal);
/**
* Finds the resource limit for a specified account and type. If the account has an infinite limit, will check
@ -85,9 +102,10 @@ public interface ResourceLimitService {
*
* @param account
* @param type
* @param tag
* @return resource limit
*/
public long findCorrectResourceLimitForAccount(Account account, ResourceType type);
public long findCorrectResourceLimitForAccount(Account account, ResourceType type, String tag);
/**
* This call should be used when we have already queried resource limit for an account. This is to handle
@ -105,9 +123,10 @@ public interface ResourceLimitService {
*
* @param domain
* @param type
* @param tag
* @return resource limit
*/
public long findCorrectResourceLimitForDomain(Domain domain, ResourceType type);
public long findCorrectResourceLimitForDomain(Domain domain, ResourceType type, String tag);
/**
* Finds the default resource limit for a specified type.
@ -122,9 +141,10 @@ public interface ResourceLimitService {
*
* @param domain
* @param type
* @param tag
* @return resource limit
*/
public long findCorrectResourceLimitForAccountAndDomain(Account account, Domain domain, ResourceType type);
public long findCorrectResourceLimitForAccountAndDomain(Account account, Domain domain, ResourceType type, String tag);
/**
* Increments the resource count
@ -134,6 +154,7 @@ public interface ResourceLimitService {
* @param delta
*/
public void incrementResourceCount(long accountId, ResourceType type, Long... delta);
public void incrementResourceCountWithTag(long accountId, ResourceType type, String tag, Long... delta);
/**
* Decrements the resource count
@ -143,6 +164,7 @@ public interface ResourceLimitService {
* @param delta
*/
public void decrementResourceCount(long accountId, ResourceType type, Long... delta);
public void decrementResourceCountWithTag(long accountId, ResourceType type, String tag, Long... delta);
/**
* Checks if a limit has been exceeded for an account
@ -155,15 +177,17 @@ public interface ResourceLimitService {
* @throws ResourceAllocationException
*/
public void checkResourceLimit(Account account, ResourceCount.ResourceType type, long... count) throws ResourceAllocationException;
public void checkResourceLimitWithTag(Account account, ResourceCount.ResourceType type, String tag, long... count) throws ResourceAllocationException;
/**
* Gets the count of resources for a resource type and account
*
* @param account
* @param type
* @param tag
* @return count of resources
*/
public long getResourceCount(Account account, ResourceType type);
public long getResourceCount(Account account, ResourceType type, String tag);
/**
* Checks if a limit has been exceeded for an account if displayResource flag is on
@ -208,15 +232,25 @@ public interface ResourceLimitService {
*/
void decrementResourceCount(long accountId, ResourceType type, Boolean displayResource, Long... delta);
/**
* Adds a reservation that will be counted in subsequent calls to {count}getResourceCount{code} until {code}this[code}
* is closed. It will create a reservation record that will be counted when resource limits are checked.
* @param account The account for which the reservation is.
* @param displayResource whether this resource is shown to users at all (if not it is not counted to limits)
* @param type resource type
* @param delta amount to reserve (will not be <+ 0)
* @return a {code}AutoClosable{Code} object representing the resource the user needs
*/
ResourceReservation getReservation(Account account, Boolean displayResource, ResourceType type, Long delta) throws ResourceAllocationException;
List<String> getResourceLimitHostTags();
List<String> getResourceLimitHostTags(ServiceOffering serviceOffering, VirtualMachineTemplate template);
List<String> getResourceLimitStorageTags();
List<String> getResourceLimitStorageTags(DiskOffering diskOffering);
void updateTaggedResourceLimitsAndCountsForAccounts(List<AccountResponse> responses, String tag);
void updateTaggedResourceLimitsAndCountsForDomains(List<DomainResponse> responses, String tag);
void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException;
void incrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
void decrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
void incrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
void decrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template) throws ResourceAllocationException;
void incrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
void decrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
void checkVmCpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu) throws ResourceAllocationException;
void incrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu);
void decrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu);
void checkVmMemoryResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) throws ResourceAllocationException;
void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
void decrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
}

View File

@ -442,6 +442,6 @@ public class NicProfile implements InternalIdentity, Serializable {
@Override
public String toString() {
return String.format("NicProfile %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "vmId", "reservationId", "iPv4Address", "broadcastUri"));
return String.format("NicProfile %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "vmId", "deviceId", "broadcastUri", "reservationId", "iPv4Address"));
}
}

View File

@ -285,6 +285,7 @@ public class ApiConstants {
public static final String LAST_SERVER_STOP = "lastserverstop";
public static final String LEVEL = "level";
public static final String LENGTH = "length";
public static final String LIMIT = "limit";
public static final String LIMIT_CPU_USE = "limitcpuuse";
public static final String LIST_HOSTS = "listhosts";
public static final String LOCK = "lock";
@ -382,6 +383,7 @@ public class ApiConstants {
public static final String RECONNECT = "reconnect";
public static final String RECOVER = "recover";
public static final String REQUIRES_HVM = "requireshvm";
public static final String RESOURCE_COUNT = "resourcecount";
public static final String RESOURCE_NAME = "resourcename";
public static final String RESOURCE_TYPE = "resourcetype";
public static final String RESOURCE_TYPE_NAME = "resourcetypename";
@ -422,8 +424,9 @@ public class ApiConstants {
public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid";
public static final String SNAPSHOT_TYPE = "snapshottype";
public static final String SNAPSHOT_QUIESCEVM = "quiescevm";
public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot";
public static final String SOURCE_ZONE_ID = "sourcezoneid";
public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine";
public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot";
public static final String START_DATE = "startdate";
public static final String START_ID = "startid";
public static final String START_IP = "startip";
@ -451,6 +454,7 @@ public class ApiConstants {
public static final String TIMEOUT = "timeout";
public static final String TIMEZONE = "timezone";
public static final String TIMEZONEOFFSET = "timezoneoffset";
public static final String TOTAL = "total";
public static final String TOTAL_SUBNETS = "totalsubnets";
public static final String TYPE = "type";
public static final String TRUST_STORE = "truststore";
@ -727,6 +731,7 @@ public class ApiConstants {
public static final String POLICY_UUID = "policyuuid";
public static final String RULE_UUID = "ruleuuid";
public static final String DIRECTION = "direction";
public static final String TAGGED_RESOURCES = "taggedresources";
public static final String TAG_UUID = "taguuid";
public static final String TAG_TYPE = "tagtype";
public static final String TAG_VALUE = "tagvalue";

View File

@ -20,10 +20,6 @@ import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag;
import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiConstants.DomainDetails;
@ -33,9 +29,13 @@ import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.commons.collections.CollectionUtils;
import com.cloud.domain.Domain;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag;
@APICommand(name = "listDomains", description = "Lists domains and provides detailed information for listed domains", responseObject = DomainResponse.class, responseView = ResponseView.Restricted, entityType = {Domain.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@ -71,6 +71,9 @@ public class ListDomainsCmd extends BaseListCmd implements UserCmd {
description = "flag to display the resource icon for domains")
private Boolean showIcon;
@Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for resource type to return usage", since = "4.20.0")
private String tag;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -110,10 +113,14 @@ public class ListDomainsCmd extends BaseListCmd implements UserCmd {
return dv;
}
public Boolean getShowIcon() {
public boolean getShowIcon() {
return showIcon != null ? showIcon : false;
}
public String getTag() {
return tag;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -128,12 +135,17 @@ public class ListDomainsCmd extends BaseListCmd implements UserCmd {
ListResponse<DomainResponse> response = _queryService.searchForDomains(this);
response.setResponseName(getCommandName());
this.setResponseObject(response);
if (response != null && response.getCount() > 0 && getShowIcon()) {
updateDomainResponse(response.getResponses());
}
updateDomainResponse(response.getResponses());
}
private void updateDomainResponse(List<DomainResponse> response) {
protected void updateDomainResponse(List<DomainResponse> response) {
if (CollectionUtils.isEmpty(response)) {
return;
}
_resourceLimitService.updateTaggedResourceLimitsAndCountsForDomains(response, getTag());
if (!getShowIcon()) {
return;
}
for (DomainResponse domainResponse : response) {
ResourceIcon resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.Domain, domainResponse.getId());
if (resourceIcon == null) {

View File

@ -71,6 +71,9 @@ public class ListCapacityCmd extends BaseListCmd {
@Parameter(name = ApiConstants.SORT_BY, type = CommandType.STRING, since = "3.0.0", description = "Sort the results. Available values: Usage")
private String sortBy;
@Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for the resource type", since = "4.20.0")
private String tag;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -107,6 +110,10 @@ public class ListCapacityCmd extends BaseListCmd {
return null;
}
public String getTag() {
return tag;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -65,7 +65,7 @@ public class FindStoragePoolsForMigrationCmd extends BaseListCmd {
@Override
public void execute() {
Pair<List<? extends StoragePool>, List<? extends StoragePool>> pools = _mgr.listStoragePoolsForMigrationOfVolume(getId());
Pair<List<? extends StoragePool>, List<? extends StoragePool>> pools = _mgr.listStoragePoolsForMigrationOfVolume(getId(), getKeyword());
ListResponse<StoragePoolResponse> response = new ListResponse<StoragePoolResponse>();
List<StoragePoolResponse> poolResponses = new ArrayList<StoragePoolResponse>();
@ -85,7 +85,8 @@ public class FindStoragePoolsForMigrationCmd extends BaseListCmd {
poolResponses.add(poolResponse);
}
sortPoolsBySuitabilityAndName(poolResponses);
response.setResponses(poolResponses);
List<StoragePoolResponse> pagingList = com.cloud.utils.StringUtils.applyPagination(poolResponses, this.getStartIndex(), this.getPageSizeVal());
response.setResponses(pagingList, poolResponses.size());
response.setResponseName(getCommandName());
this.setResponseObject(response);
}

View File

@ -31,6 +31,7 @@ import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.commons.collections.CollectionUtils;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.server.ResourceIcon;
@ -73,6 +74,9 @@ public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserC
description = "flag to display the resource icon for accounts")
private Boolean showIcon;
@Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for resource type to return usage", since = "4.20.0")
private String tag;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -116,10 +120,14 @@ public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserC
return dv;
}
public Boolean getShowIcon() {
public boolean getShowIcon() {
return showIcon != null ? showIcon : false;
}
public String getTag() {
return tag;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -134,12 +142,17 @@ public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserC
ListResponse<AccountResponse> response = _queryService.searchForAccounts(this);
response.setResponseName(getCommandName());
setResponseObject(response);
if (response != null && response.getCount() > 0 && getShowIcon()) {
updateAccountResponse(response.getResponses());
}
updateAccountResponse(response.getResponses());
}
private void updateAccountResponse(List<AccountResponse> response) {
protected void updateAccountResponse(List<AccountResponse> response) {
if (CollectionUtils.isEmpty(response)) {
return;
}
_resourceLimitService.updateTaggedResourceLimitsAndCountsForAccounts(response, getTag());
if (!getShowIcon()) {
return;
}
for (AccountResponse accountResponse : response) {
ResourceIcon resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.Account, accountResponse.getObjectId());
if (resourceIcon == null) {

View File

@ -16,17 +16,16 @@
// under the License.
package org.apache.cloudstack.api.command.user.offering;
import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
@APICommand(name = "listDiskOfferings", description = "Lists all available disk offerings.", responseObject = DiskOfferingResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@ -65,6 +64,13 @@ public class ListDiskOfferingsCmd extends BaseListProjectAndAccountResourcesCmd
since = "4.19")
private String storageType;
@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID,
type = CommandType.UUID,
entityType = UserVmResponse.class,
description = "The ID of a virtual machine. Pass this in if you want to see the suitable disk offering that can be used to create and add a disk to the virtual machine. Suitability is returned with suitableforvirtualmachine flag in the response",
since = "4.20.0")
private Long virtualMachineId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -93,13 +99,16 @@ public class ListDiskOfferingsCmd extends BaseListProjectAndAccountResourcesCmd
return storageType;
}
public Long getVirtualMachineId() {
return virtualMachineId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() {
ListResponse<DiskOfferingResponse> response = _queryService.searchForDiskOfferings(this);
response.setResponseName(getCommandName());
this.setResponseObject(response);

View File

@ -16,15 +16,15 @@
// under the License.
package org.apache.cloudstack.api.command.user.offering;
import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.TemplateResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
@APICommand(name = "listServiceOfferings", description = "Lists all available service offerings.", responseObject = ServiceOfferingResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@ -92,6 +92,14 @@ public class ListServiceOfferingsCmd extends BaseListProjectAndAccountResourcesC
since = "4.19")
private String storageType;
@Parameter(name = ApiConstants.TEMPLATE_ID,
type = CommandType.UUID,
entityType = TemplateResponse.class,
description = "The ID of the template that listed offerings must support",
since = "4.20.0")
private Long templateId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -138,6 +146,10 @@ public class ListServiceOfferingsCmd extends BaseListProjectAndAccountResourcesC
return storageType;
}
public Long getTemplateId() {
return templateId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -19,8 +19,6 @@ package org.apache.cloudstack.api.command.user.resource;
import java.util.ArrayList;
import java.util.List;
import com.cloud.configuration.Resource;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
@ -28,7 +26,9 @@ import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ResourceLimitResponse;
import com.cloud.configuration.Resource;
import com.cloud.configuration.ResourceLimit;
import com.cloud.exception.InvalidParameterValueException;
@APICommand(name = "listResourceLimits", description = "Lists resource limits.", responseObject = ResourceLimitResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@ -72,6 +72,10 @@ public class ListResourceLimitsCmd extends BaseListProjectAndAccountResourcesCmd
+ "secondary_storage - SecondaryStorage. Total secondary storage space (in GiB) a user can use. ")
private String resourceTypeName;
@Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for the resource type", since = "4.20.0")
private String tag;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -88,6 +92,10 @@ public class ListResourceLimitsCmd extends BaseListProjectAndAccountResourcesCmd
return resourceTypeName;
}
public String getTag() {
return tag;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -96,7 +104,7 @@ public class ListResourceLimitsCmd extends BaseListProjectAndAccountResourcesCmd
public void execute() {
List<? extends ResourceLimit> result =
_resourceLimitService.searchForLimits(id, _accountService.finalyzeAccountId(this.getAccountName(), this.getDomainId(), this.getProjectId(), false), this.getDomainId(),
getResourceTypeEnum(), this.getStartIndex(), this.getPageSizeVal());
getResourceTypeEnum(), getTag(), this.getStartIndex(), this.getPageSizeVal());
ListResponse<ResourceLimitResponse> response = new ListResponse<ResourceLimitResponse>();
List<ResourceLimitResponse> limitResponses = new ArrayList<ResourceLimitResponse>();
for (ResourceLimit limit : result) {

View File

@ -75,6 +75,9 @@ public class UpdateResourceCountCmd extends BaseCmd {
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "Update resource limits for project")
private Long projectId;
@Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for the resource type", since = "4.20.0")
private String tag;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -91,6 +94,10 @@ public class UpdateResourceCountCmd extends BaseCmd {
return resourceType;
}
public String getTag() {
return tag;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -117,7 +124,7 @@ public class UpdateResourceCountCmd extends BaseCmd {
@Override
public void execute() {
List<? extends ResourceCount> result =
_resourceLimitService.recalculateResourceCount(_accountService.finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), getResourceType());
_resourceLimitService.recalculateResourceCount(_accountService.finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), getResourceType(), getTag());
if ((result != null) && (result.size() > 0)) {
ListResponse<ResourceCountResponse> response = new ListResponse<ResourceCountResponse>();
@ -125,7 +132,6 @@ public class UpdateResourceCountCmd extends BaseCmd {
for (ResourceCount count : result) {
ResourceCountResponse resourceCountResponse = _responseGenerator.createResourceCountResponse(count);
resourceCountResponse.setObjectName("resourcecount");
countResponses.add(resourceCountResponse);
}

View File

@ -70,6 +70,9 @@ public class UpdateResourceLimitCmd extends BaseCmd {
+ "11 - SecondaryStorage. Total secondary storage space (in GiB) a user can use. ")
private Integer resourceType;
@Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for the resource type", since = "4.20.0")
private String tag;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -82,6 +85,10 @@ public class UpdateResourceLimitCmd extends BaseCmd {
return domainId;
}
public String getTag() {
return tag;
}
public Integer getResourceType() {
return resourceType;
}
@ -102,7 +109,7 @@ public class UpdateResourceLimitCmd extends BaseCmd {
@Override
public void execute() {
ResourceLimit result = _resourceLimitService.updateResourceLimit(_accountService.finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), resourceType, max);
ResourceLimit result = _resourceLimitService.updateResourceLimit(_accountService.finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), resourceType, max, getTag());
if (result != null || (result == null && max != null && max.longValue() == -1L)) {
ResourceLimitResponse response = _responseGenerator.createResourceLimitResponse(result);
response.setResponseName(getCommandName());

View File

@ -16,7 +16,6 @@
// under the License.
package org.apache.cloudstack.api.command.user.template;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@ -44,6 +43,9 @@ public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd implements Use
description = "the type of the template. Valid options are: USER/VNF (for all users) and SYSTEM/ROUTING/BUILTIN (for admins only).")
private String templateType;
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.", since = "4.20.0")
private String templateTag;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -57,6 +59,10 @@ public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd implements Use
return templateType;
}
public String getTemplateTag() {
return templateTag;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -267,6 +267,10 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou
@Param(description = "Base64 string representation of the resource icon", since = "4.16.0.0")
ResourceIconResponse icon;
@SerializedName(ApiConstants.TAGGED_RESOURCES)
@Param(description = "The tagged resource limit and count for the account", since = "4.20.0")
List<TaggedResourceLimitAndCountResponse> taggedResources;
@Override
public String getObjectId() {
return id;
@ -545,4 +549,9 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou
public void setResourceIconResponse(ResourceIconResponse icon) {
this.icon = icon;
}
@Override
public void setTaggedResourceLimitsAndCounts(List<TaggedResourceLimitAndCountResponse> taggedResourceLimitsAndCounts) {
this.taggedResources = taggedResourceLimitsAndCounts;
}
}

View File

@ -16,12 +16,11 @@
// 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;
import com.google.gson.annotations.SerializedName;
public class CapacityResponse extends BaseResponse {
@SerializedName(ApiConstants.TYPE)
@ -72,6 +71,10 @@ public class CapacityResponse extends BaseResponse {
@Param(description = "the percentage of capacity currently in use")
private String percentUsed;
@SerializedName(ApiConstants.TAG)
@Param(description = "The tag for the capacity type", since = "4.20.0")
private String tag;
public Short getCapacityType() {
return capacityType;
}
@ -167,4 +170,8 @@ public class CapacityResponse extends BaseResponse {
public void setPercentUsed(String percentUsed) {
this.percentUsed = percentUsed;
}
public void setTag(String tag) {
this.tag = tag;
}
}

View File

@ -169,6 +169,10 @@ public class DiskOfferingResponse extends BaseResponseWithAnnotations {
@Param(description = "additional key/value details tied with this disk offering", since = "4.17")
private Map<String, String> details;
@SerializedName(ApiConstants.SUITABLE_FOR_VM)
@Param(description = "Returns true if the disk offering is suitable for the given virtual machine for disk creation otherwise false", since = "4.20.0")
private Boolean suitableForVm;
public Boolean getDisplayOffering() {
return displayOffering;
}
@ -391,4 +395,8 @@ public class DiskOfferingResponse extends BaseResponseWithAnnotations {
public void setDetails(Map<String, String> details) {
this.details = details;
}
public void setSuitableForVm(Boolean suitableForVm) {
this.suitableForVm = suitableForVm;
}
}

View File

@ -26,6 +26,7 @@ import com.cloud.domain.Domain;
import com.cloud.serializer.Param;
import java.util.Date;
import java.util.List;
import java.util.Map;
@EntityReference(value = Domain.class)
@ -184,6 +185,10 @@ public class DomainResponse extends BaseResponseWithAnnotations implements Resou
@Param(description = "details for the domain")
private Map<String, String> details;
@SerializedName(ApiConstants.TAGGED_RESOURCES)
@Param(description = "The tagged resource limit and count for the domain", since = "4.20.0")
List<TaggedResourceLimitAndCountResponse> taggedResources;
public String getId() {
return this.id;
}
@ -447,4 +452,9 @@ public class DomainResponse extends BaseResponseWithAnnotations implements Resou
public void setDetails(Map<String, String> details) {
this.details = details;
}
@Override
public void setTaggedResourceLimitsAndCounts(List<TaggedResourceLimitAndCountResponse> taggedResourceLimitsAndCounts) {
this.taggedResources = taggedResourceLimitsAndCounts;
}
}

View File

@ -216,6 +216,10 @@ public class ProjectResponse extends BaseResponse implements ResourceLimitAndCou
@Param(description = "the date this project was created", since = "4.16.0")
private Date created;
@SerializedName(ApiConstants.TAGGED_RESOURCES)
@Param(description = "The tagged resource limit and count for the project", since = "4.20.0")
List<TaggedResourceLimitAndCountResponse> taggedResources;
public void setId(String id) {
this.id = id;
}
@ -447,4 +451,9 @@ public class ProjectResponse extends BaseResponse implements ResourceLimitAndCou
public void setCreated(Date created) {
this.created = created;
}
@Override
public void setTaggedResourceLimitsAndCounts(List<TaggedResourceLimitAndCountResponse> taggedResourceLimitsAndCounts) {
this.taggedResources = taggedResourceLimitsAndCounts;
}
}

View File

@ -16,13 +16,12 @@
// under the License.
package org.apache.cloudstack.api.response;
import com.cloud.configuration.Resource;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.configuration.Resource;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
public class ResourceCountResponse extends BaseResponse implements ControlledEntityResponse {
@ -54,10 +53,14 @@ public class ResourceCountResponse extends BaseResponse implements ControlledEnt
@Param(description = "resource type name. Values include user_vm, public_ip, volume, snapshot, template, project, network, vpc, cpu, memory, primary_storage, secondary_storage.")
private String resourceTypeName;
@SerializedName("resourcecount")
@Param(description = "resource count")
@SerializedName(ApiConstants.RESOURCE_COUNT)
@Param(description = "The resource count")
private long resourceCount;
@SerializedName(ApiConstants.TAG)
@Param(description = "Tag for the resource", since = "4.20.0")
private String tag;
@Override
public void setAccountName(String accountName) {
this.accountName = accountName;
@ -92,4 +95,7 @@ public class ResourceCountResponse extends BaseResponse implements ControlledEnt
this.projectName = projectName;
}
public void setTag(String tag) {
this.tag = tag;
}
}

View File

@ -20,6 +20,8 @@ have limits and resource count **/
package org.apache.cloudstack.api.response;
import java.util.List;
public interface ResourceLimitAndCountResponse {
public void setNetworkLimit(String networkLimit);
@ -92,4 +94,6 @@ public interface ResourceLimitAndCountResponse {
public void setVmRunning(Integer vmRunning);
public void setTaggedResourceLimitsAndCounts(List<TaggedResourceLimitAndCountResponse> taggedResourceLimitsAndCounts);
}

View File

@ -16,15 +16,14 @@
// under the License.
package org.apache.cloudstack.api.response;
import com.cloud.configuration.Resource;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.configuration.Resource;
import com.cloud.configuration.ResourceLimit;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@EntityReference(value = ResourceLimit.class)
@SuppressWarnings("unused")
@ -61,6 +60,10 @@ public class ResourceLimitResponse extends BaseResponse implements ControlledEnt
@Param(description = "the project name of the resource limit")
private String projectName;
@SerializedName(ApiConstants.TAG)
@Param(description = "The tag for the resource limit", since = "4.20.0")
private String tag;
@Override
public void setAccountName(String accountName) {
this.accountName = accountName;
@ -94,4 +97,8 @@ public class ResourceLimitResponse extends BaseResponse implements ControlledEnt
public void setProjectId(String projectId) {
this.projectId = projectId;
}
public void setTag(String tag) {
this.tag = tag;
}
}

View File

@ -0,0 +1,86 @@
// 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 org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.configuration.Resource;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class TaggedResourceLimitAndCountResponse extends BaseResponse {
@SerializedName(ApiConstants.RESOURCE_TYPE)
@Param(description = "Numerical value for the type of the resource. See the ResourceType for more information on these values.")
private Integer resourceType;
@SerializedName(ApiConstants.RESOURCE_TYPE_NAME)
@Param(description = "Name for the type of the resource")
private String resourceTypeName;
@SerializedName(ApiConstants.TAG)
@Param(description = "The tag for the resource type")
private String tag;
@SerializedName(ApiConstants.LIMIT)
@Param(description = "The limit for the resource count for the type and tag for the owner")
private Long limit;
@SerializedName(ApiConstants.TOTAL)
@Param(description = "The total amount of the resource for the type and tag that is used by the owner")
private Long total;
@SerializedName(ApiConstants.AVAILABLE)
@Param(description = "The available amount of the resource for the type and tag that is available for the owner")
private Long available;
public void setResourceType(Resource.ResourceType resourceType) {
this.resourceType = resourceType.getOrdinal();
this.resourceTypeName = resourceType.getName();
}
public void setTag(String tag) {
this.tag = tag;
}
public void setLimit(Long limit) {
this.limit = limit;
}
public void setTotal(Long total) {
this.total = total;
}
public void setAvailable(Long available) {
this.available = available;
}
public Long getLimit() {
return limit;
}
public Long getTotal() {
return total;
}
public Long getAvailable() {
return available;
}
}

View File

@ -18,9 +18,10 @@
//
package org.apache.cloudstack.user;
import com.cloud.configuration.Resource;
import org.apache.cloudstack.api.InternalIdentity;
import com.cloud.configuration.Resource;
/**
* an interface defining an {code}AutoClosable{code} reservation object
*/
@ -33,5 +34,7 @@ ResourceReservation extends InternalIdentity {
Resource.ResourceType getResourceType();
String getTag();
Long getReservedAmount();
}

View File

@ -0,0 +1,77 @@
// 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.domain;
import java.util.List;
import org.apache.cloudstack.api.response.DomainResponse;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import com.cloud.user.ResourceLimitService;
@RunWith(MockitoJUnitRunner.class)
public class ListDomainsCmdTest {
@Mock
ResourceLimitService resourceLimitService;
@Test
public void testGetShowIcon() {
ListDomainsCmd cmd = new ListDomainsCmd();
ReflectionTestUtils.setField(cmd, "showIcon", null);
Assert.assertFalse(cmd.getShowIcon());
ReflectionTestUtils.setField(cmd, "showIcon", false);
Assert.assertFalse(cmd.getShowIcon());
ReflectionTestUtils.setField(cmd, "showIcon", true);
Assert.assertTrue(cmd.getShowIcon());
}
@Test
public void testGetTag() {
ListDomainsCmd cmd = new ListDomainsCmd();
ReflectionTestUtils.setField(cmd, "tag", null);
Assert.assertNull(cmd.getTag());
String tag = "ABC";
ReflectionTestUtils.setField(cmd, "tag", tag);
Assert.assertEquals(tag, cmd.getTag());
}
@Test
public void testUpdateDomainResponseNoDomains() {
ListDomainsCmd cmd = new ListDomainsCmd();
cmd._resourceLimitService = resourceLimitService;
cmd.updateDomainResponse(null);
Mockito.verify(resourceLimitService, Mockito.never()).updateTaggedResourceLimitsAndCountsForDomains(Mockito.anyList(), Mockito.anyString());
}
@Test
public void testUpdateDomainResponseWithDomains() {
ListDomainsCmd cmd = new ListDomainsCmd();
cmd._resourceLimitService = resourceLimitService;
ReflectionTestUtils.setField(cmd, "tag", "abc");
cmd.updateDomainResponse(List.of(Mockito.mock(DomainResponse.class)));
Mockito.verify(resourceLimitService, Mockito.times(1)).updateTaggedResourceLimitsAndCountsForDomains(Mockito.any(), Mockito.any());
}
}

View File

@ -0,0 +1,34 @@
// 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.resource;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.test.util.ReflectionTestUtils;
public class ListCapacityCmdTest {
@Test
public void testGetTag() {
ListCapacityCmd cmd = new ListCapacityCmd();
ReflectionTestUtils.setField(cmd, "tag", null);
Assert.assertNull(cmd.getTag());
String tag = "ABC";
ReflectionTestUtils.setField(cmd, "tag", tag);
Assert.assertEquals(tag, cmd.getTag());
}
}

View File

@ -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.command.user.account;
import java.util.List;
import org.apache.cloudstack.api.response.AccountResponse;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import com.cloud.user.ResourceLimitService;
@RunWith(MockitoJUnitRunner.class)
public class ListAccountsCmdTest {
@Mock
ResourceLimitService resourceLimitService;
@Test
public void testGetShowIcon() {
ListAccountsCmd cmd = new ListAccountsCmd();
ReflectionTestUtils.setField(cmd, "showIcon", null);
Assert.assertFalse(cmd.getShowIcon());
ReflectionTestUtils.setField(cmd, "showIcon", false);
Assert.assertFalse(cmd.getShowIcon());
ReflectionTestUtils.setField(cmd, "showIcon", true);
Assert.assertTrue(cmd.getShowIcon());
}
@Test
public void testGetTag() {
ListAccountsCmd cmd = new ListAccountsCmd();
ReflectionTestUtils.setField(cmd, "tag", null);
Assert.assertNull(cmd.getTag());
String tag = "ABC";
ReflectionTestUtils.setField(cmd, "tag", tag);
Assert.assertEquals(tag, cmd.getTag());
}
@Test
public void testUpdateDomainResponseNoDomains() {
ListAccountsCmd cmd = new ListAccountsCmd();
cmd._resourceLimitService = resourceLimitService;
cmd.updateAccountResponse(null);
Mockito.verify(resourceLimitService, Mockito.never()).updateTaggedResourceLimitsAndCountsForAccounts(Mockito.anyList(), Mockito.anyString());
}
@Test
public void testUpdateDomainResponseWithDomains() {
ListAccountsCmd cmd = new ListAccountsCmd();
cmd._resourceLimitService = resourceLimitService;
ReflectionTestUtils.setField(cmd, "tag", "abc");
cmd.updateAccountResponse(List.of(Mockito.mock(AccountResponse.class)));
Mockito.verify(resourceLimitService, Mockito.times(1)).updateTaggedResourceLimitsAndCountsForAccounts(Mockito.any(), Mockito.any());
}
}

View File

@ -0,0 +1,37 @@
// 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.user.offering;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class ListDiskOfferingsCmdTest {
@Test
public void testGetVirtualMachineId() {
ListDiskOfferingsCmd cmd = new ListDiskOfferingsCmd();
ReflectionTestUtils.setField(cmd, "virtualMachineId", null);
Assert.assertNull(cmd.getVirtualMachineId());
Long id = 100L;
ReflectionTestUtils.setField(cmd, "virtualMachineId", id);
Assert.assertEquals(id, cmd.getVirtualMachineId());
}
}

View File

@ -0,0 +1,38 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.offering;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class ListServiceOfferingsCmdTest {
@Test
public void testGetTemplateId() {
ListServiceOfferingsCmd cmd = new ListServiceOfferingsCmd();
ReflectionTestUtils.setField(cmd, "templateId", null);
Assert.assertNull(cmd.getTemplateId());
Long id = 100L;
ReflectionTestUtils.setField(cmd, "templateId", id);
Assert.assertEquals(id, cmd.getTemplateId());
}
}

View File

@ -0,0 +1,37 @@
// 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.user.resource;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class ListResourceLimitsCmdTest {
@Test
public void testGetTag() {
ListResourceLimitsCmd cmd = new ListResourceLimitsCmd();
ReflectionTestUtils.setField(cmd, "tag", null);
Assert.assertNull(cmd.getTag());
String tag = "ABC";
ReflectionTestUtils.setField(cmd, "tag", tag);
Assert.assertEquals(tag, cmd.getTag());
}
}

View File

@ -0,0 +1,37 @@
// 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.user.resource;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class UpdateResourceCountCmdTest {
@Test
public void testGetTag() {
UpdateResourceCountCmd cmd = new UpdateResourceCountCmd();
ReflectionTestUtils.setField(cmd, "tag", null);
Assert.assertNull(cmd.getTag());
String tag = "ABC";
ReflectionTestUtils.setField(cmd, "tag", tag);
Assert.assertEquals(tag, cmd.getTag());
}
}

View File

@ -0,0 +1,37 @@
// 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.user.resource;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class UpdateResourceLimitCmdTest {
@Test
public void testGetTag() {
UpdateResourceLimitCmd cmd = new UpdateResourceLimitCmd();
ReflectionTestUtils.setField(cmd, "tag", null);
Assert.assertNull(cmd.getTag());
String tag = "ABC";
ReflectionTestUtils.setField(cmd, "tag", tag);
Assert.assertEquals(tag, cmd.getTag());
}
}

View File

@ -0,0 +1,49 @@
// 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.user.template;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import com.cloud.storage.Storage;
@RunWith(MockitoJUnitRunner.class)
public class UpdateTemplateCmdTest {
@Test
public void testGetTemplateType() {
UpdateTemplateCmd cmd = new UpdateTemplateCmd();
ReflectionTestUtils.setField(cmd, "templateType", null);
Assert.assertNull(cmd.getTemplateType());
String type = Storage.TemplateType.ROUTING.toString();
ReflectionTestUtils.setField(cmd, "templateTag", type);
Assert.assertEquals(type, cmd.getTemplateTag());
}
@Test
public void testGetTemplateTag() {
UpdateTemplateCmd cmd = new UpdateTemplateCmd();
ReflectionTestUtils.setField(cmd, "templateTag", null);
Assert.assertNull(cmd.getTemplateTag());
String tag = "ABC";
ReflectionTestUtils.setField(cmd, "templateTag", tag);
Assert.assertEquals(tag, cmd.getTemplateTag());
}
}

View File

@ -54,6 +54,8 @@ public class GsonHelper {
GsonBuilder LOGGERBuilder = new GsonBuilder();
LOGGERBuilder.disableHtmlEscaping();
LOGGERBuilder.setExclusionStrategies(new LoggingExclusionStrategy(LOGGER));
LOGGERBuilder.serializeSpecialFloatingPointValues();
// maybe add LOGGERBuilder.serializeNulls(); as well?
s_gogger = setDefaultGsonConfig(LOGGERBuilder);
LOGGER.info("Default Builder inited.");
}

View File

@ -290,4 +290,6 @@ public interface VirtualMachineManager extends Manager {
HashMap<Long, List<? extends VmNetworkStats>> getVmNetworkStatistics(long hostId, String hostName, Map<Long, ? extends VirtualMachine> vmMap);
Map<Long, Boolean> getDiskOfferingSuitabilityForVm(long vmId, List<Long> diskOfferingIds);
}

View File

@ -52,9 +52,12 @@ public interface StoragePoolAllocator extends Adapter {
* avoid
* @param int returnUpTo (use -1 to return all possible pools)
* @param boolean bypassStorageTypeCheck allows bypassing useLocalStorage check for provided DiskProfile when true
* @param String keyword if passed, will only return storage pools that contain this keyword in the name
* @return List<StoragePool> List of storage pools that are suitable for the
* VM
**/
List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck, String keyword);
List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck);

View File

@ -277,6 +277,8 @@ public interface StorageManager extends StorageService {
CapacityVO getStoragePoolUsedStats(Long poolId, Long clusterId, Long podId, Long zoneId);
CapacityVO getStoragePoolUsedStats(Long zoneId, Long podId, Long clusterId, List<Long> poolIds);
List<StoragePoolVO> ListByDataCenterHypervisor(long datacenterId, HypervisorType type);
List<VMInstanceVO> listByStoragePool(long storagePoolId);
@ -303,6 +305,9 @@ public interface StorageManager extends StorageService {
boolean storagePoolHasEnoughIops(List<Pair<Volume, DiskProfile>> volumeDiskProfilePairs, StoragePool pool);
boolean storagePoolHasEnoughIops(Long requestedIops, StoragePool pool);
boolean storagePoolHasEnoughSpace(Long size, StoragePool pool);
boolean storagePoolHasEnoughSpace(List<Pair<Volume, DiskProfile>> volumeDiskProfilePairs, StoragePool pool);
/**
@ -335,6 +340,8 @@ public interface StorageManager extends StorageService {
boolean isStoragePoolCompliantWithStoragePolicy(List<Pair<Volume, DiskProfile>> volumes, StoragePool pool) throws StorageUnavailableException;
boolean isStoragePoolCompliantWithStoragePolicy(long diskOfferingId, StoragePool pool) throws StorageUnavailableException;
boolean registerHostListener(String providerUuid, HypervisorHostListener listener);
boolean connectHostToSharedPool(long hostId, long poolId) throws StorageUnavailableException, StorageConflictException;

View File

@ -19,6 +19,7 @@ package com.cloud.vm;
import static com.cloud.configuration.ConfigurationManagerImpl.MIGRATE_VM_ACROSS_CLUSTERS;
import java.lang.reflect.Field;
import java.net.URI;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -154,7 +155,6 @@ import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.vo.DomainRouterJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.capacity.CapacityManager;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.ClusterDetailsVO;
import com.cloud.dc.ClusterVO;
@ -1152,7 +1152,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
// check resource count if ResourceCountRunningVMsonly.value() = true
final Account owner = _entityMgr.findById(Account.class, vm.getAccountId());
if (VirtualMachine.Type.User.equals(vm.type) && ResourceCountRunningVMsonly.value()) {
resourceCountIncrement(owner.getAccountId(),new Long(offering.getCpu()), new Long(offering.getRamSize()));
_resourceLimitMgr.incrementVmResourceCount(owner.getAccountId(), vm.isDisplay(), offering, template);
}
boolean canRetry = true;
@ -1462,7 +1462,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
} finally {
if (startedVm == null) {
if (VirtualMachine.Type.User.equals(vm.type) && ResourceCountRunningVMsonly.value()) {
resourceCountDecrement(owner.getAccountId(),new Long(offering.getCpu()), new Long(offering.getRamSize()));
_resourceLimitMgr.decrementVmResourceCount(owner.getAccountId(), vm.isDisplay(), offering, template);
}
if (canRetry) {
try {
@ -2281,7 +2281,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
if (result) {
if (VirtualMachine.Type.User.equals(vm.type) && ResourceCountRunningVMsonly.value()) {
ServiceOfferingVO offering = _offeringDao.findById(vm.getId(), vm.getServiceOfferingId());
resourceCountDecrement(vm.getAccountId(),new Long(offering.getCpu()), new Long(offering.getRamSize()));
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
_resourceLimitMgr.decrementVmResourceCount(vm.getAccountId(), vm.isDisplay(), offering, template);
}
} else {
throw new CloudRuntimeException("unable to stop " + vm);
@ -5679,18 +5680,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
return workJob;
}
protected void resourceCountIncrement (long accountId, Long cpu, Long memory) {
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.user_vm);
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.cpu, cpu);
_resourceLimitMgr.incrementResourceCount(accountId, ResourceType.memory, memory);
}
protected void resourceCountDecrement (long accountId, Long cpu, Long memory) {
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.user_vm);
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.cpu, cpu);
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.memory, memory);
}
@Override
public UserVm restoreVirtualMachine(final long vmId, final Long newTemplateId) throws ResourceUnavailableException, InsufficientCapacityException {
final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
@ -6118,4 +6107,48 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
return vmNetworkStatsById;
}
protected boolean isDiskOfferingSuitableForVm(VMInstanceVO vm, VirtualMachineProfile profile, long podId, long clusterId, long hostId, long diskOfferingId) {
DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
VolumeVO dummyVolume = new VolumeVO("Data", vm.getDataCenterId(), podId, vm.getAccountId(),
vm.getDomainId(), vm.getId(), null, null, diskOffering.getProvisioningType(), diskOffering.getDiskSize(), Type.DATADISK);
try {
Field idField = dummyVolume.getClass().getDeclaredField("id");
idField.setAccessible(true);
idField.set(dummyVolume, Volume.DISK_OFFERING_SUITABILITY_CHECK_VOLUME_ID);
} catch (NoSuchFieldException | IllegalAccessException ignored) {
return false;
}
dummyVolume.setDiskOfferingId(diskOfferingId);
DiskProfile diskProfile = new DiskProfile(dummyVolume, diskOffering, profile.getHypervisorType());
diskProfile.setMinIops(diskOffering.getMinIops());
diskProfile.setMaxIops(diskOffering.getMaxIops());
ExcludeList avoid = new ExcludeList();
DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), podId, clusterId, hostId, null, null);
for (StoragePoolAllocator allocator : _storagePoolAllocators) {
List<StoragePool> poolListFromAllocator = allocator.allocateToPool(diskProfile, profile, plan, avoid, 1);
if (CollectionUtils.isNotEmpty(poolListFromAllocator)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Found a suitable pool: %s for disk offering: %s", poolListFromAllocator.get(0).getName(), diskOffering.getName()));
}
return true;
}
}
return false;
}
@Override
public Map<Long, Boolean> getDiskOfferingSuitabilityForVm(long vmId, List<Long> diskOfferingIds) {
VMInstanceVO vm = _vmDao.findById(vmId);
VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
Pair<Long, Long> clusterAndHost = findClusterAndHostIdForVm(vm, false);
Long clusterId = clusterAndHost.first();
Cluster cluster = _clusterDao.findById(clusterId);
Map<Long, Boolean> result = new HashMap<>();
for (Long diskOfferingId : diskOfferingIds) {
result.put(diskOfferingId, isDiskOfferingSuitableForVm(vm, profile, cluster.getPodId(), clusterId, clusterAndHost.second(), diskOfferingId));
}
return result;
}
}

View File

@ -2371,12 +2371,12 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
@DB
protected void releaseNic(final VirtualMachineProfile vmProfile, final long nicId) throws ConcurrentOperationException, ResourceUnavailableException {
final Pair<Network, NicProfile> networkToRelease = Transaction.execute(new TransactionCallback<Pair<Network, NicProfile>>() {
final Pair<Network, NicProfile> networkToRelease = Transaction.execute(new TransactionCallback<>() {
@Override
public Pair<Network, NicProfile> doInTransaction(final TransactionStatus status) {
final NicVO nic = _nicDao.lockRow(nicId, true);
if (nic == null) {
throw new ConcurrentOperationException("Unable to acquire lock on nic " + nic);
throw new ConcurrentOperationException(String.format("Unable to acquire lock on nic id=%d", nicId));
}
final Nic.State originalState = nic.getState();
@ -2390,6 +2390,9 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
final NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, _networkModel
.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vmProfile.getHypervisorType(), network));
if (guru.release(profile, vmProfile, nic.getReservationId())) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("The nic %s on %s was released according to %s by guru %s, now updating record.", nic, profile, vmProfile, guru));
}
applyProfileToNicForRelease(nic, profile);
nic.setState(Nic.State.Allocated);
if (originalState == Nic.State.Reserved) {
@ -2399,7 +2402,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
}
// Perform release on network elements
return new Pair<Network, NicProfile>(network, profile);
return new Pair<>(network, profile);
} else {
nic.setState(Nic.State.Allocated);
updateNic(nic, network.getId(), -1);
@ -2496,7 +2499,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
for (final NetworkElement element : networkElements) {
if (providersToImplement.contains(element.getProvider())) {
if (logger.isDebugEnabled()) {
logger.debug("Asking " + element.getName() + " to release " + nic);
logger.debug(String.format("Asking %s to release %s, according to the reservation strategy %s", element.getName(), nic, nic.getReservationStrategy()));
}
try {
element.release(network, profile, vm, null);

View File

@ -130,6 +130,7 @@ import com.cloud.storage.Volume.Type;
import com.cloud.storage.VolumeApiService;
import com.cloud.storage.VolumeDetailVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VMTemplateDetailsDao;
@ -245,6 +246,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
PassphraseDao passphraseDao;
@Inject
StoragePoolHostDao storagePoolHostDao;
@Inject
DiskOfferingDao diskOfferingDao;
@Inject
protected SnapshotHelper snapshotHelper;
@ -878,9 +881,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
if (vm.getType() == VirtualMachine.Type.User) {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size,
Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume());
_resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume, vol.isDisplayVolume());
_resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, vol.isDisplayVolume(), new Long(vol.getSize()));
_resourceLimitMgr.incrementVolumeResourceCount(vm.getAccountId(), vol.isDisplayVolume(), vol.getSize(), offering);
}
DiskProfile diskProfile = toDiskProfile(vol, offering);
@ -962,8 +963,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offeringId, vol.getTemplateId(), size,
Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume());
_resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume, vol.isDisplayVolume());
_resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, vol.isDisplayVolume(), new Long(vol.getSize()));
_resourceLimitMgr.incrementVolumeResourceCount(vm.getAccountId(), vol.isDisplayVolume(), vol.getSize(), offering);
}
return toDiskProfile(vol, offering);
}
@ -1142,6 +1142,10 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
// Moving of Volume is successful, decrement the volume resource count from secondary for an account and increment it into primary storage under same account.
_resourceLimitMgr.decrementResourceCount(volumeInfo.getAccountId(), ResourceType.secondary_storage, volumeInfo.getSize());
_resourceLimitMgr.incrementResourceCount(volumeInfo.getAccountId(), ResourceType.primary_storage, volumeInfo.getSize());
List<String> tags = _resourceLimitMgr.getResourceLimitStorageTags(diskVO);
for (String tag : tags) {
_resourceLimitMgr.incrementResourceCountWithTag(volumeInfo.getAccountId(), ResourceType.primary_storage, tag, volumeInfo.getSize());
}
}
}
@ -2102,8 +2106,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
if (volume.getState() == Volume.State.Allocated) {
_volsDao.remove(volume.getId());
stateTransitTo(volume, Volume.Event.DestroyRequested);
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplay());
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplay(), new Long(volume.getSize()));
_resourceLimitMgr.decrementVolumeResourceCount(volume.getAccountId(), volume.isDisplay(), volume.getSize(), diskOfferingDao.findByIdIncludingRemoved(volume.getDiskOfferingId()));
} else {
destroyVolumeInContext(volume);
}

View File

@ -23,6 +23,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@ -50,27 +51,12 @@ import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.ClusterDetailsVO;
import com.cloud.dc.Pod;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlanningManager;
import com.cloud.hypervisor.HypervisorGuruManager;
import com.cloud.org.Cluster;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.Journal;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.dao.UserVmDetailsDao;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.commons.collections.MapUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@ -83,6 +69,7 @@ import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.springframework.test.util.ReflectionTestUtils;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Command;
@ -90,16 +77,25 @@ import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.ClusterDetailsVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.Pod;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.deploy.DeploymentPlanningManager;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.HypervisorGuruManager;
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
@ -117,11 +113,19 @@ import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.Journal;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
import org.springframework.test.util.ReflectionTestUtils;
@RunWith(MockitoJUnitRunner.class)
public class VirtualMachineManagerImplTest {
@ -206,6 +210,8 @@ public class VirtualMachineManagerImplTest {
@Mock
private HypervisorGuruManager _hvGuruMgr;
@Mock
private ClusterDao clusterDao;
@Mock
private ClusterDetailsDao _clusterDetailsDao;
@Mock
private UserVmDetailsDao userVmDetailsDao;
@ -1181,4 +1187,47 @@ public class VirtualMachineManagerImplTest {
assertNull(vmInstance.getPodIdToDeployIn());
}
@Test
public void testIsDiskOfferingSuitableForVmSuccess() {
Mockito.doReturn(Mockito.mock(DiskOfferingVO.class)).when(diskOfferingDaoMock).findById(anyLong());
List<StoragePool> poolListMock = new ArrayList<>();
poolListMock.add(storagePoolVoMock);
Mockito.doReturn(poolListMock).when(storagePoolAllocatorMock).allocateToPool(any(DiskProfile.class), any(VirtualMachineProfile.class), any(DeploymentPlan.class),
any(ExcludeList.class), Mockito.eq(1));
boolean result = virtualMachineManagerImpl.isDiskOfferingSuitableForVm(vmInstanceMock, virtualMachineProfileMock, 1L, 1L,1L, 1L);
assertTrue(result);
}
@Test
public void testIsDiskOfferingSuitableForVmNegative() {
Mockito.doReturn(Mockito.mock(DiskOfferingVO.class)).when(diskOfferingDaoMock).findById(anyLong());
Mockito.doReturn(new ArrayList<>()).when(storagePoolAllocatorMock).allocateToPool(any(DiskProfile.class), any(VirtualMachineProfile.class), any(DeploymentPlan.class),
any(ExcludeList.class), Mockito.eq(1));
boolean result = virtualMachineManagerImpl.isDiskOfferingSuitableForVm(vmInstanceMock, virtualMachineProfileMock, 1L, 1L,1L, 1L);
assertFalse(result);
}
@Test
public void testGetDiskOfferingSuitabilityForVm() {
Mockito.doReturn(vmInstanceMock).when(vmInstanceDaoMock).findById(1L);
Mockito.when(vmInstanceMock.getHostId()).thenReturn(1L);
Mockito.doReturn(hostMock).when(hostDaoMock).findById(1L);
Mockito.when(hostMock.getClusterId()).thenReturn(1L);
ClusterVO cluster = Mockito.mock(ClusterVO.class);
Mockito.when(cluster.getPodId()).thenReturn(1L);
Mockito.doReturn(cluster).when(clusterDao).findById(1L);
List<Long> diskOfferingIds = List.of(1L, 2L);
Mockito.doReturn(false).when(virtualMachineManagerImpl)
.isDiskOfferingSuitableForVm(eq(vmInstanceMock), any(VirtualMachineProfile.class),
eq(1L), eq(1L), eq(1L), eq(1L));
Mockito.doReturn(true).when(virtualMachineManagerImpl)
.isDiskOfferingSuitableForVm(eq(vmInstanceMock), any(VirtualMachineProfile.class),
eq(1L), eq(1L), eq(1L), eq(2L));
Map<Long, Boolean> result = virtualMachineManagerImpl.getDiskOfferingSuitabilityForVm(1L, diskOfferingIds);
assertTrue(MapUtils.isNotEmpty(result));
assertEquals(2, result.keySet().size());
assertFalse(result.get(1L));
assertTrue(result.get(2L));
}
}

View File

@ -80,6 +80,9 @@ public class CapacityVO implements Capacity {
@Transient
private Long allocatedCapacity;
@Transient
private String tag;
public CapacityVO() {
}
@ -221,6 +224,15 @@ public class CapacityVO implements Capacity {
this.allocatedCapacity = allocatedCapacity;
}
@Override
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
@Override
public String getUuid() {
return null; //To change body of implemented methods use File | Settings | File Templates.

View File

@ -44,6 +44,8 @@ public interface CapacityDao extends GenericDao<CapacityVO, Long> {
List<SummedCapacity> findCapacityBy(Integer capacityType, Long zoneId, Long podId, Long clusterId);
List<SummedCapacity> findFilteredCapacityBy(Integer capacityType, Long zoneId, Long podId, Long clusterId, List<Long> hostIds, List<Long> poolIds);
List<Long> listPodsByHostCapacities(long zoneId, int requiredCpu, long requiredRam, short capacityType);
Pair<List<Long>, Map<Long, Double>> orderPodsByAggregateCapacity(long zoneId, short capacityType);
@ -51,7 +53,8 @@ public interface CapacityDao extends GenericDao<CapacityVO, Long> {
List<SummedCapacity> findCapacityBy(Integer capacityType, Long zoneId,
Long podId, Long clusterId, String resourceState);
List<SummedCapacity> listCapacitiesGroupedByLevelAndType(Integer capacityType, Long zoneId, Long podId, Long clusterId, int level, Long limit);
List<SummedCapacity> listCapacitiesGroupedByLevelAndType(Integer capacityType, Long zoneId, Long podId,
Long clusterId, int level, List<Long> hostIds, List<Long> poolIds, Long limit);
void updateCapacityState(Long dcId, Long podId, Long clusterId, Long hostId, String capacityState, short[] capacityType);

View File

@ -26,11 +26,11 @@ import java.util.Map;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityVO;
@ -339,7 +339,8 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
}
@Override
public List<SummedCapacity> listCapacitiesGroupedByLevelAndType(Integer capacityType, Long zoneId, Long podId, Long clusterId, int level, Long limit) {
public List<SummedCapacity> listCapacitiesGroupedByLevelAndType(Integer capacityType, Long zoneId, Long podId,
Long clusterId, int level, List<Long> hostIds, List<Long> poolIds, Long limit) {
StringBuilder finalQuery = new StringBuilder();
TransactionLegacy txn = TransactionLegacy.currentTxn();
@ -378,6 +379,18 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
finalQuery.append(" AND capacity_type = ?");
resourceIdList.add(capacityType.longValue());
}
if (CollectionUtils.isNotEmpty(hostIds)) {
finalQuery.append(String.format(" AND capacity.host_id IN (%s)", StringUtils.join(hostIds, ",")));
if (capacityType == null) {
finalQuery.append(String.format(" AND capacity_type NOT IN (%s)", StringUtils.join(Capacity.STORAGE_CAPACITY_TYPES, ",")));
}
}
if (CollectionUtils.isNotEmpty(poolIds)) {
finalQuery.append(String.format(" AND capacity.host_id IN (%s)", StringUtils.join(poolIds, ",")));
if (capacityType == null) {
finalQuery.append(String.format(" AND capacity_type IN (%s)", StringUtils.join(Capacity.STORAGE_CAPACITY_TYPES, ",")));
}
}
switch (level) {
case 1: // List all the capacities grouped by zone, capacity Type
@ -461,8 +474,37 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
}
}
protected String getHostAndPoolConditionForFilteredCapacity(Integer capacityType, List<Long> hostIds, List<Long> poolIds) {
StringBuilder sql = new StringBuilder();
if (CollectionUtils.isEmpty(hostIds) && CollectionUtils.isEmpty(poolIds)) {
return "";
}
sql.append(" AND (");
boolean hostConditionAdded = false;
if (CollectionUtils.isNotEmpty(hostIds) && (capacityType == null || !Capacity.STORAGE_CAPACITY_TYPES.contains(capacityType.shortValue()))) {
sql.append(String.format("(capacity.host_id IN (%s)", StringUtils.join(hostIds, ",")));
if (capacityType == null) {
sql.append(String.format(" AND capacity_type NOT IN (%s)", StringUtils.join(Capacity.STORAGE_CAPACITY_TYPES, ",")));
}
sql.append(")");
hostConditionAdded = true;
}
if (CollectionUtils.isNotEmpty(poolIds) && (capacityType == null || Capacity.STORAGE_CAPACITY_TYPES.contains(capacityType.shortValue()))) {
if (hostConditionAdded) {
sql.append(" OR ");
}
sql.append(String.format("(capacity.host_id IN (%s)", StringUtils.join(poolIds, ",")));
if (capacityType == null || Capacity.STORAGE_CAPACITY_TYPES.contains(capacityType.shortValue())) {
sql.append(String.format(" AND capacity_type IN (%s)", StringUtils.join(Capacity.STORAGE_CAPACITY_TYPES, ",")));
}
sql.append(")");
}
sql.append(")");
return sql.toString();
}
@Override
public List<SummedCapacity> findCapacityBy(Integer capacityType, Long zoneId, Long podId, Long clusterId) {
public List<SummedCapacity> findFilteredCapacityBy(Integer capacityType, Long zoneId, Long podId, Long clusterId, List<Long> hostIds, List<Long> poolIds) {
TransactionLegacy txn = TransactionLegacy.currentTxn();
PreparedStatement pstmt = null;
@ -516,6 +558,8 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
resourceIdList.add(capacityType.longValue());
}
sql.append(getHostAndPoolConditionForFilteredCapacity(capacityType, hostIds, poolIds));
if (podId == null && clusterId == null) {
sql.append(" GROUP BY capacity_type, data_center_id");
} else {
@ -591,6 +635,11 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
}
}
@Override
public List<SummedCapacity> findCapacityBy(Integer capacityType, Long zoneId, Long podId, Long clusterId) {
return findFilteredCapacityBy(capacityType, zoneId, podId, clusterId, null, null);
}
public void updateAllocated(Long hostId, long allocatedAmount, short capacityType, boolean add) {
TransactionLegacy txn = TransactionLegacy.currentTxn();
PreparedStatement pstmt = null;
@ -702,6 +751,7 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
public Long clusterId;
public Long podId;
public Long dcId;
public String tag;
public SummedCapacity() {
}
@ -790,6 +840,14 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
public void setAllocatedCapacity(Long sumAllocated) {
this.sumAllocated = sumAllocated;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
}
@Override

View File

@ -47,10 +47,13 @@ public class ResourceCountVO implements ResourceCount {
@Column(name = "count")
private long count;
@Column(name = "tag")
private String tag;
public ResourceCountVO() {
}
public ResourceCountVO(ResourceType type, long count, long ownerId, ResourceOwnerType ownerType) {
public ResourceCountVO(ResourceType type, long count, long ownerId, ResourceOwnerType ownerType, String tag) {
this.type = type;
this.count = count;
@ -59,6 +62,11 @@ public class ResourceCountVO implements ResourceCount {
} else if (ownerType == ResourceOwnerType.Domain) {
this.domainId = ownerId;
}
this.tag = tag;
}
public ResourceCountVO(ResourceType type, long count, long ownerId, ResourceOwnerType ownerType) {
this(type, count, ownerId, ownerType, null);
}
@Override
@ -99,7 +107,7 @@ public class ResourceCountVO implements ResourceCount {
@Override
public String toString() {
return new StringBuilder("REsourceCount[").append("-")
return new StringBuilder("ResourceCount[").append("-")
.append(id)
.append("-")
.append(type)
@ -107,6 +115,8 @@ public class ResourceCountVO implements ResourceCount {
.append(accountId)
.append("-")
.append(domainId)
.append("-")
.append(tag)
.append("]")
.toString();
}
@ -136,4 +146,13 @@ public class ResourceCountVO implements ResourceCount {
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
@Override
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
}

View File

@ -47,10 +47,13 @@ public class ResourceLimitVO implements ResourceLimit {
@Column(name = "max")
private Long max;
@Column(name = "tag")
private String tag;
public ResourceLimitVO() {
}
public ResourceLimitVO(ResourceCount.ResourceType type, Long max, long ownerId, ResourceOwnerType ownerType) {
public ResourceLimitVO(ResourceCount.ResourceType type, Long max, long ownerId, ResourceOwnerType ownerType, String tag) {
this.type = type;
this.max = max;
@ -59,6 +62,11 @@ public class ResourceLimitVO implements ResourceLimit {
} else if (ownerType == ResourceOwnerType.Domain) {
this.domainId = ownerId;
}
this.tag = tag;
}
public ResourceLimitVO(ResourceCount.ResourceType type, Long max, long ownerId, ResourceOwnerType ownerType) {
this(type, max, ownerId, ownerType, null);
}
@Override
@ -123,4 +131,12 @@ public class ResourceLimitVO implements ResourceLimit {
this.accountId = accountId;
}
@Override
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
}

View File

@ -26,18 +26,20 @@ import com.cloud.utils.db.GenericDao;
public interface ResourceCountDao extends GenericDao<ResourceCountVO, Long> {
/**
* @param domainId the id of the domain to get the resource count
* @param ownerId the id of the owner to get the resource count
* @param type the type of resource (e.g. user_vm, public_ip, volume)
* @param tag for the type of resource
* @return the count of resources in use for the given type and domain
*/
long getResourceCount(long ownerId, ResourceOwnerType ownerType, ResourceType type);
long getResourceCount(long ownerId, ResourceOwnerType ownerType, ResourceType type, String tag);
/**
* @param domainId the id of the domain to set the resource count
* @param ownerId the id of the owner to set the resource count
* @param type the type of resource (e.g. user_vm, public_ip, volume)
* @param the count of resources in use for the given type and domain
* @param tag the tag for the type of resource
* @param count the count of resources in use for the given type and domain
*/
void setResourceCount(long ownerId, ResourceOwnerType ownerType, ResourceType type, long count);
void setResourceCount(long ownerId, ResourceOwnerType ownerType, ResourceType type, String tag, long count);
boolean updateById(long id, boolean increment, long delta);
@ -45,13 +47,13 @@ public interface ResourceCountDao extends GenericDao<ResourceCountVO, Long> {
List<ResourceCountVO> listByOwnerId(long ownerId, ResourceOwnerType ownerType);
ResourceCountVO findByOwnerAndType(long ownerId, ResourceOwnerType ownerType, ResourceType type);
ResourceCountVO findByOwnerAndTypeAndTag(long ownerId, ResourceOwnerType ownerType, ResourceType type, String tag);
List<ResourceCountVO> listResourceCountByOwnerType(ResourceOwnerType ownerType);
Set<Long> listAllRowsToUpdate(long ownerId, ResourceOwnerType ownerType, ResourceType type);
Set<Long> listAllRowsToUpdate(long ownerId, ResourceOwnerType ownerType, ResourceType type, String tag);
Set<Long> listRowsToUpdateForDomain(long domainId, ResourceType type);
Set<Long> listRowsToUpdateForDomain(long domainId, ResourceType type, String tag);
long removeEntriesByOwner(long ownerId, ResourceOwnerType ownerType);
@ -68,4 +70,6 @@ public interface ResourceCountDao extends GenericDao<ResourceCountVO, Long> {
* Side note: This method is not using the "resource_count" table. It is executing the actual count instead.
*/
long countMemoryAllocatedToAccount(long accountId);
void removeResourceCountsForNonMatchingTags(Long ownerId, ResourceOwnerType ownerType, List<ResourceType> types, List<String> tags);
}

View File

@ -20,6 +20,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -27,6 +28,9 @@ import java.util.Set;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import com.cloud.configuration.Resource;
@ -37,6 +41,7 @@ import com.cloud.configuration.ResourceLimit;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.user.AccountVO;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
@ -49,6 +54,8 @@ import com.cloud.utils.exception.CloudRuntimeException;
@Component
public class ResourceCountDaoImpl extends GenericDaoBase<ResourceCountVO, Long> implements ResourceCountDao {
private final SearchBuilder<ResourceCountVO> TypeSearch;
private final SearchBuilder<ResourceCountVO> TypeNullTagSearch;
private final SearchBuilder<ResourceCountVO> NonMatchingTagsSearch;
private final SearchBuilder<ResourceCountVO> AccountSearch;
private final SearchBuilder<ResourceCountVO> DomainSearch;
@ -63,8 +70,24 @@ public class ResourceCountDaoImpl extends GenericDaoBase<ResourceCountVO, Long>
TypeSearch.and("type", TypeSearch.entity().getType(), SearchCriteria.Op.EQ);
TypeSearch.and("accountId", TypeSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
TypeSearch.and("domainId", TypeSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
TypeSearch.and("tag", TypeSearch.entity().getTag(), SearchCriteria.Op.EQ);
TypeSearch.done();
TypeNullTagSearch = createSearchBuilder();
TypeNullTagSearch.and("type", TypeNullTagSearch.entity().getType(), SearchCriteria.Op.EQ);
TypeNullTagSearch.and("accountId", TypeNullTagSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
TypeNullTagSearch.and("domainId", TypeNullTagSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
TypeNullTagSearch.and("tag", TypeNullTagSearch.entity().getTag(), SearchCriteria.Op.NULL);
TypeNullTagSearch.done();
NonMatchingTagsSearch = createSearchBuilder();
NonMatchingTagsSearch.and("accountId", NonMatchingTagsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
NonMatchingTagsSearch.and("domainId", NonMatchingTagsSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
NonMatchingTagsSearch.and("types", NonMatchingTagsSearch.entity().getType(), SearchCriteria.Op.IN);
NonMatchingTagsSearch.and("tagNotNull", NonMatchingTagsSearch.entity().getTag(), SearchCriteria.Op.NNULL);
NonMatchingTagsSearch.and("tags", NonMatchingTagsSearch.entity().getTag(), SearchCriteria.Op.NIN);
NonMatchingTagsSearch.done();
AccountSearch = createSearchBuilder();
DomainSearch = createSearchBuilder();
}
@ -85,9 +108,12 @@ public class ResourceCountDaoImpl extends GenericDaoBase<ResourceCountVO, Long>
}
@Override
public ResourceCountVO findByOwnerAndType(long ownerId, ResourceOwnerType ownerType, ResourceType type) {
SearchCriteria<ResourceCountVO> sc = TypeSearch.create();
public ResourceCountVO findByOwnerAndTypeAndTag(long ownerId, ResourceOwnerType ownerType, ResourceType type, String tag) {
SearchCriteria<ResourceCountVO> sc = tag != null ? TypeSearch.create() : TypeNullTagSearch.create();
sc.setParameters("type", type);
if (tag != null) {
sc.setParameters("tag", tag);
}
if (ownerType == ResourceOwnerType.Account) {
sc.setParameters("accountId", ownerId);
@ -101,8 +127,8 @@ public class ResourceCountDaoImpl extends GenericDaoBase<ResourceCountVO, Long>
}
@Override
public long getResourceCount(long ownerId, ResourceOwnerType ownerType, ResourceType type) {
ResourceCountVO vo = findByOwnerAndType(ownerId, ownerType, type);
public long getResourceCount(long ownerId, ResourceOwnerType ownerType, ResourceType type, String tag) {
ResourceCountVO vo = findByOwnerAndTypeAndTag(ownerId, ownerType, type, tag);
if (vo != null) {
return vo.getCount();
} else {
@ -111,8 +137,8 @@ public class ResourceCountDaoImpl extends GenericDaoBase<ResourceCountVO, Long>
}
@Override
public void setResourceCount(long ownerId, ResourceOwnerType ownerType, ResourceType type, long count) {
ResourceCountVO resourceCountVO = findByOwnerAndType(ownerId, ownerType, type);
public void setResourceCount(long ownerId, ResourceOwnerType ownerType, ResourceType type, String tag, long count) {
ResourceCountVO resourceCountVO = findByOwnerAndTypeAndTag(ownerId, ownerType, type, tag);
if (resourceCountVO != null && count != resourceCountVO.getCount()) {
resourceCountVO.setCount(count);
update(resourceCountVO.getId(), resourceCountVO);
@ -129,38 +155,59 @@ public class ResourceCountDaoImpl extends GenericDaoBase<ResourceCountVO, Long>
}
@Override
public Set<Long> listRowsToUpdateForDomain(long domainId, ResourceType type) {
public Set<Long> listRowsToUpdateForDomain(long domainId, ResourceType type, String tag) {
Set<Long> rowIds = new HashSet<Long>();
Set<Long> domainIdsToUpdate = _domainDao.getDomainParentIds(domainId);
for (Long domainIdToUpdate : domainIdsToUpdate) {
ResourceCountVO domainCountRecord = findByOwnerAndType(domainIdToUpdate, ResourceOwnerType.Domain, type);
ResourceCountVO domainCountRecord = findByOwnerAndTypeAndTag(domainIdToUpdate, ResourceOwnerType.Domain, type, tag);
if (domainCountRecord != null) {
rowIds.add(domainCountRecord.getId());
} else {
if (StringUtils.isNotEmpty(tag)) {
ResourceCountVO resourceCountVO = createTaggedResourceCount(domainIdToUpdate, ResourceOwnerType.Domain, type, tag);
rowIds.add(resourceCountVO.getId());
}
}
}
return rowIds;
}
@Override
public Set<Long> listAllRowsToUpdate(long ownerId, ResourceOwnerType ownerType, ResourceType type) {
public Set<Long> listAllRowsToUpdate(long ownerId, ResourceOwnerType ownerType, ResourceType type, String tag) {
Set<Long> rowIds = new HashSet<Long>();
if (ownerType == ResourceOwnerType.Account) {
//get records for account
ResourceCountVO accountCountRecord = findByOwnerAndType(ownerId, ResourceOwnerType.Account, type);
ResourceCountVO accountCountRecord = findByOwnerAndTypeAndTag(ownerId, ResourceOwnerType.Account, type, tag);
if (accountCountRecord != null) {
rowIds.add(accountCountRecord.getId());
} else {
if (StringUtils.isNotEmpty(tag)) {
ResourceCountVO resourceCountVO = createTaggedResourceCount(ownerId, ownerType, type, tag);
rowIds.add(resourceCountVO.getId());
}
}
//get records for account's domain and all its parent domains
rowIds.addAll(listRowsToUpdateForDomain(_accountDao.findByIdIncludingRemoved(ownerId).getDomainId(), type));
rowIds.addAll(listRowsToUpdateForDomain(_accountDao.findByIdIncludingRemoved(ownerId).getDomainId(), type, tag));
} else if (ownerType == ResourceOwnerType.Domain) {
return listRowsToUpdateForDomain(ownerId, type);
rowIds = listRowsToUpdateForDomain(ownerId, type, tag);
}
return rowIds;
}
protected ResourceCountVO createTaggedResourceCount(long ownerId, ResourceLimit.ResourceOwnerType ownerType, ResourceType resourceType, String tag) {
ResourceCountVO taggedResourceCountVO = new ResourceCountVO(resourceType, 0, ownerId, ownerType, tag);
return persist(taggedResourceCountVO);
}
protected void createTaggedResourceCounts(long ownerId, ResourceLimit.ResourceOwnerType ownerType, ResourceType resourceType, List<String> tags) {
for (String tag : tags) {
createTaggedResourceCount(ownerId, ownerType, resourceType, tag);
}
}
@Override
@DB
public void createResourceCounts(long ownerId, ResourceLimit.ResourceOwnerType ownerType) {
@ -169,9 +216,23 @@ public class ResourceCountDaoImpl extends GenericDaoBase<ResourceCountVO, Long>
txn.start();
ResourceType[] resourceTypes = Resource.ResourceType.values();
List<String> hostTags = new ArrayList<>();
if (StringUtils.isNotEmpty(ResourceLimitService.ResourceLimitHostTags.value())) {
hostTags = Arrays.asList(ResourceLimitService.ResourceLimitHostTags.value().split(","));
}
List<String> storageTags = new ArrayList<>();
if (StringUtils.isNotEmpty(ResourceLimitService.ResourceLimitStorageTags.value())) {
storageTags = Arrays.asList(ResourceLimitService.ResourceLimitStorageTags.value().split(","));
}
for (ResourceType resourceType : resourceTypes) {
ResourceCountVO resourceCountVO = new ResourceCountVO(resourceType, 0, ownerId, ownerType);
persist(resourceCountVO);
if (ResourceLimitService.HostTagsSupportingTypes.contains(resourceType)) {
createTaggedResourceCounts(ownerId, ownerType, resourceType, hostTags);
}
if (ResourceLimitService.StorageTagsSupportingTypes.contains(resourceType)) {
createTaggedResourceCounts(ownerId, ownerType, resourceType, storageTags);
}
}
txn.commit();
@ -266,4 +327,22 @@ public class ResourceCountDaoImpl extends GenericDaoBase<ResourceCountVO, Long>
}
}
@Override
public void removeResourceCountsForNonMatchingTags(Long ownerId, ResourceOwnerType ownerType, List<ResourceType> types, List<String> tags) {
SearchCriteria<ResourceCountVO> sc = NonMatchingTagsSearch.create();
if (ObjectUtils.allNotNull(ownerId, ownerType)) {
if (ResourceOwnerType.Account.equals(ownerType)) {
sc.setParameters("accountId", ownerId);
} else {
sc.setParameters("domainId", ownerId);
}
}
if (CollectionUtils.isNotEmpty(types)) {
sc.setParameters("types", types.stream().map(ResourceType::getName).toArray());
}
if (CollectionUtils.isNotEmpty(tags)) {
sc.setParameters("tags", tags.toArray());
}
remove(sc);
}
}

View File

@ -18,6 +18,7 @@ package com.cloud.configuration.dao;
import java.util.List;
import com.cloud.configuration.Resource;
import com.cloud.configuration.Resource.ResourceOwnerType;
import com.cloud.configuration.ResourceCount;
import com.cloud.configuration.ResourceLimitVO;
@ -31,7 +32,8 @@ public interface ResourceLimitDao extends GenericDao<ResourceLimitVO, Long> {
ResourceCount.ResourceType getLimitType(String type);
ResourceLimitVO findByOwnerIdAndType(long ownerId, ResourceOwnerType ownerType, ResourceCount.ResourceType type);
ResourceLimitVO findByOwnerIdAndTypeAndTag(long ownerId, ResourceOwnerType ownerType, ResourceCount.ResourceType type, String tag);
long removeEntriesByOwner(Long ownerId, ResourceOwnerType ownerType);
void removeResourceLimitsForNonMatchingTags(Long ownerId, ResourceOwnerType ownerType, List<Resource.ResourceType> types, List<String> tags);
}

View File

@ -20,6 +20,8 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;
import com.cloud.configuration.Resource;
@ -33,19 +35,36 @@ import com.cloud.utils.db.SearchCriteria;
@Component
public class ResourceLimitDaoImpl extends GenericDaoBase<ResourceLimitVO, Long> implements ResourceLimitDao {
private SearchBuilder<ResourceLimitVO> IdTypeSearch;
private SearchBuilder<ResourceLimitVO> IdTypeTagSearch;
private SearchBuilder<ResourceLimitVO> IdTypeNullTagSearch;
private SearchBuilder<ResourceLimitVO> NonMatchingTagsSearch;
public ResourceLimitDaoImpl() {
IdTypeSearch = createSearchBuilder();
IdTypeSearch.and("type", IdTypeSearch.entity().getType(), SearchCriteria.Op.EQ);
IdTypeSearch.and("domainId", IdTypeSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
IdTypeSearch.and("accountId", IdTypeSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
IdTypeSearch.done();
IdTypeTagSearch = createSearchBuilder();
IdTypeTagSearch.and("type", IdTypeTagSearch.entity().getType(), SearchCriteria.Op.EQ);
IdTypeTagSearch.and("domainId", IdTypeTagSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
IdTypeTagSearch.and("accountId", IdTypeTagSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
IdTypeTagSearch.and("tag", IdTypeTagSearch.entity().getTag(), SearchCriteria.Op.EQ);
IdTypeNullTagSearch = createSearchBuilder();
IdTypeNullTagSearch.and("type", IdTypeNullTagSearch.entity().getType(), SearchCriteria.Op.EQ);
IdTypeNullTagSearch.and("domainId", IdTypeNullTagSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
IdTypeNullTagSearch.and("accountId", IdTypeNullTagSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
IdTypeNullTagSearch.and("tag", IdTypeNullTagSearch.entity().getTag(), SearchCriteria.Op.NULL);
IdTypeNullTagSearch.done();
NonMatchingTagsSearch = createSearchBuilder();
NonMatchingTagsSearch.and("accountId", NonMatchingTagsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
NonMatchingTagsSearch.and("domainId", NonMatchingTagsSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
NonMatchingTagsSearch.and("types", NonMatchingTagsSearch.entity().getType(), SearchCriteria.Op.IN);
NonMatchingTagsSearch.and("tagNotNull", NonMatchingTagsSearch.entity().getTag(), SearchCriteria.Op.NNULL);
NonMatchingTagsSearch.and("tags", NonMatchingTagsSearch.entity().getTag(), SearchCriteria.Op.NIN);
NonMatchingTagsSearch.done();
}
@Override
public List<ResourceLimitVO> listByOwner(Long ownerId, ResourceOwnerType ownerType) {
SearchCriteria<ResourceLimitVO> sc = IdTypeSearch.create();
SearchCriteria<ResourceLimitVO> sc = IdTypeTagSearch.create();
if (ownerType == ResourceOwnerType.Account) {
sc.setParameters("accountId", ownerId);
@ -81,9 +100,12 @@ public class ResourceLimitDaoImpl extends GenericDaoBase<ResourceLimitVO, Long>
}
@Override
public ResourceLimitVO findByOwnerIdAndType(long ownerId, ResourceOwnerType ownerType, ResourceCount.ResourceType type) {
SearchCriteria<ResourceLimitVO> sc = IdTypeSearch.create();
public ResourceLimitVO findByOwnerIdAndTypeAndTag(long ownerId, ResourceOwnerType ownerType, ResourceCount.ResourceType type, String tag) {
SearchCriteria<ResourceLimitVO> sc = tag != null ? IdTypeTagSearch.create() : IdTypeNullTagSearch.create();
sc.setParameters("type", type);
if (tag != null) {
sc.setParameters("tag", tag);
}
if (ownerType == ResourceOwnerType.Account) {
sc.setParameters("accountId", ownerId);
@ -98,7 +120,7 @@ public class ResourceLimitDaoImpl extends GenericDaoBase<ResourceLimitVO, Long>
@Override
public long removeEntriesByOwner(Long ownerId, ResourceOwnerType ownerType) {
SearchCriteria<ResourceLimitVO> sc = IdTypeSearch.create();
SearchCriteria<ResourceLimitVO> sc = IdTypeTagSearch.create();
if (ownerType == ResourceOwnerType.Account) {
sc.setParameters("accountId", ownerId);
@ -109,4 +131,23 @@ public class ResourceLimitDaoImpl extends GenericDaoBase<ResourceLimitVO, Long>
}
return 0;
}
@Override
public void removeResourceLimitsForNonMatchingTags(Long ownerId, ResourceOwnerType ownerType, List<ResourceType> types, List<String> tags) {
SearchCriteria<ResourceLimitVO> sc = NonMatchingTagsSearch.create();
if (ObjectUtils.allNotNull(ownerId, ownerType)) {
if (ResourceOwnerType.Account.equals(ownerType)) {
sc.setParameters("accountId", ownerId);
} else {
sc.setParameters("domainId", ownerId);
}
}
if (CollectionUtils.isNotEmpty(types)) {
sc.setParameters("types", types.stream().map(ResourceType::getName).toArray());
}
if (CollectionUtils.isNotEmpty(tags)) {
sc.setParameters("tags", tags.toArray());
}
remove(sc);
}
}

View File

@ -16,8 +16,11 @@
// under the License.
package com.cloud.host;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@ -39,21 +42,21 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import org.apache.cloudstack.utils.jsinterpreter.TagAsRuleHelper;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.agent.api.VgpuTypesInfo;
import com.cloud.host.dao.HostTagsDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.offering.ServiceOffering;
import com.cloud.resource.ResourceState;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.util.StoragePoolTypeConverter;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.db.GenericDao;
import java.util.Arrays;
import org.apache.cloudstack.utils.jsinterpreter.TagAsRuleHelper;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
@Entity
@Table(name = "host")
@ -764,7 +767,28 @@ public class HostVO implements Host {
this.uuid = uuid;
}
public boolean checkHostServiceOfferingTags(ServiceOffering serviceOffering){
public boolean checkHostServiceOfferingAndTemplateTags(ServiceOffering serviceOffering, VirtualMachineTemplate template) {
if (serviceOffering == null || template == null) {
return false;
}
if (StringUtils.isEmpty(serviceOffering.getHostTag()) && StringUtils.isEmpty(template.getTemplateTag())) {
return true;
}
if (getHostTags() == null) {
return false;
}
HashSet<String> hostTagsSet = new HashSet<>(getHostTags());
List<String> tags = new ArrayList<>();
if (StringUtils.isNotEmpty(serviceOffering.getHostTag())) {
tags.addAll(Arrays.asList(serviceOffering.getHostTag().split(",")));
}
if (StringUtils.isNotEmpty(template.getTemplateTag()) && !tags.contains(template.getTemplateTag())) {
tags.add(template.getTemplateTag());
}
return hostTagsSet.containsAll(tags);
}
public boolean checkHostServiceOfferingTags(ServiceOffering serviceOffering) {
if (serviceOffering == null) {
return false;
}
@ -776,7 +800,6 @@ public class HostVO implements Host {
if (StringUtils.isEmpty(serviceOffering.getHostTag())) {
return true;
}
List<String> serviceOfferingTags = Arrays.asList(serviceOffering.getHostTag().split(","));
return this.getHostTags() != null && this.getHostTags().containsAll(serviceOfferingTags);
}

View File

@ -63,7 +63,7 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
void loadHostTags(HostVO host);
List<HostVO> listByHostTag(Host.Type type, Long clusterId, Long podId, long dcId, String hostTag);
List<HostVO> listByHostTag(Host.Type type, Long clusterId, Long podId, Long dcId, String hostTag);
List<HostVO> findAndUpdateApplianceToLoad(long lastPingSecondsAfter, long managementServerId);

View File

@ -780,7 +780,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
}
@Override
public List<HostVO> listByHostTag(Host.Type type, Long clusterId, Long podId, long dcId, String hostTag) {
public List<HostVO> listByHostTag(Host.Type type, Long clusterId, Long podId, Long dcId, String hostTag) {
SearchBuilder<HostVO> hostSearch = createSearchBuilder();
HostVO entity = hostSearch.entity();
hostSearch.and("type", entity.getType(), SearchCriteria.Op.EQ);
@ -798,7 +798,9 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
if (clusterId != null) {
sc.setParameters("cluster", clusterId);
}
sc.setParameters("dc", dcId);
if (dcId != null) {
sc.setParameters("dc", dcId);
}
sc.setParameters("status", Status.Up.toString());
sc.setParameters("resourceState", ResourceState.Enabled.toString());

View File

@ -55,4 +55,6 @@ public interface ServiceOfferingDao extends GenericDao<ServiceOfferingVO, Long>
List<ServiceOfferingVO> listPublicByCpuAndMemory(Integer cpus, Integer memory);
ServiceOfferingVO findServiceOfferingByComputeOnlyDiskOffering(long diskOfferingId);
List<ServiceOfferingVO> listByHostTag(String tag);
}

View File

@ -291,4 +291,22 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
}
return vos.get(0);
}
@Override
public List<ServiceOfferingVO> listByHostTag(String tag) {
SearchBuilder<ServiceOfferingVO> sb = createSearchBuilder();
sb.and("tagNotNull", sb.entity().getHostTag(), SearchCriteria.Op.NNULL);
sb.and().op("tagEq", sb.entity().getHostTag(), SearchCriteria.Op.EQ);
sb.or("tagStartLike", sb.entity().getHostTag(), SearchCriteria.Op.LIKE);
sb.or("tagMidLike", sb.entity().getHostTag(), SearchCriteria.Op.LIKE);
sb.or("tagEndLike", sb.entity().getHostTag(), SearchCriteria.Op.LIKE);
sb.cp();
sb.done();
SearchCriteria<ServiceOfferingVO> sc = sb.create();
sc.setParameters("tagEq", tag);
sc.setParameters("tagStartLike", tag + ",%");
sc.setParameters("tagMidLike", "%," + tag + ",%");
sc.setParameters("tagEndLike", "%," + tag);
return listBy(sc);
}
}

View File

@ -31,5 +31,6 @@ public interface DiskOfferingDao extends GenericDao<DiskOfferingVO, Long> {
List<DiskOfferingVO> listAllBySizeAndProvisioningType(long size, Storage.ProvisioningType provisioningType);
List<DiskOfferingVO> findCustomDiskOfferings();
List<DiskOfferingVO> listByStorageTag(String tag);
}

View File

@ -157,4 +157,22 @@ public class DiskOfferingDaoImpl extends GenericDaoBase<DiskOfferingVO, Long> im
return update(id, diskOffering);
}
@Override
public List<DiskOfferingVO> listByStorageTag(String tag) {
SearchBuilder<DiskOfferingVO> sb = createSearchBuilder();
sb.and("tagNotNull", sb.entity().getTags(), SearchCriteria.Op.NNULL);
sb.and().op("tagEq", sb.entity().getTags(), SearchCriteria.Op.EQ);
sb.or("tagStartLike", sb.entity().getTags(), SearchCriteria.Op.LIKE);
sb.or("tagMidLike", sb.entity().getTags(), SearchCriteria.Op.LIKE);
sb.or("tagEndLike", sb.entity().getTags(), SearchCriteria.Op.LIKE);
sb.cp();
sb.done();
SearchCriteria<DiskOfferingVO> sc = sb.create();
sc.setParameters("tagEq", tag);
sc.setParameters("tagStartLike", tag + ",%");
sc.setParameters("tagMidLike", "%," + tag + ",%");
sc.setParameters("tagEndLike", "%," + tag);
return listBy(sc);
}
}

View File

@ -34,5 +34,6 @@ public interface StoragePoolTagsDao extends GenericDao<StoragePoolTagVO, Long> {
StorageTagResponse newStorageTagResponse(StoragePoolTagVO tag);
List<StoragePoolTagVO> findStoragePoolTags(long poolId);
List<Long> listPoolIdsByTag(String tag);
}

View File

@ -18,12 +18,10 @@ package com.cloud.storage.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.inject.Inject;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionStatus;
import org.apache.cloudstack.api.response.StorageTagResponse;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@ -31,7 +29,10 @@ import com.cloud.storage.StoragePoolTagVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.db.TransactionStatus;
public class StoragePoolTagsDaoImpl extends GenericDaoBase<StoragePoolTagVO, Long> implements StoragePoolTagsDao {
@ -178,4 +179,15 @@ public class StoragePoolTagsDaoImpl extends GenericDaoBase<StoragePoolTagVO, Lon
return search(sc, null);
}
@Override
public List<Long> listPoolIdsByTag(String tag) {
SearchBuilder<StoragePoolTagVO> sb = createSearchBuilder();
sb.and("tag", sb.entity().getTag(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<StoragePoolTagVO> sc = sb.create();
sc.setParameters("tag", tag);
List<StoragePoolTagVO> poolRefs = search(sc, null);
return poolRefs.stream().map(StoragePoolTagVO::getPoolId).collect(Collectors.toList());
}
}

View File

@ -90,4 +90,7 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<
List<VMTemplateVO> findTemplatesLinkedToUserdata(long userdataId);
List<VMTemplateVO> listByIds(List<Long> ids);
List<VMTemplateVO> listByTemplateTag(String tag);
}

View File

@ -686,6 +686,16 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
return result;
}
@Override
public List<VMTemplateVO> listByTemplateTag(String tag) {
SearchBuilder<VMTemplateVO> sb = createSearchBuilder();
sb.and("tag", sb.entity().getTemplateTag(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<VMTemplateVO> sc = sb.create();
sc.setParameters("tag", tag);
return listIncludingRemovedBy(sc);
}
@Override
public boolean updateState(
com.cloud.template.VirtualMachineTemplate.State currentState,

View File

@ -155,4 +155,7 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long>, StateDao<Volume.S
VolumeVO findByPoolIdAndPath(long id, String path);
List<VolumeVO> listByIds(List<Long> ids);
List<VolumeVO> listAllocatedVolumesForAccountDiskOfferingIdsAndNotForVms(long accountId, List<Long> diskOfferingIds, List<Long> vmIds);
}

View File

@ -839,4 +839,28 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
sc.setParameters("idIN", ids.toArray());
return listBy(sc, null);
}
@Override
public List<VolumeVO> listAllocatedVolumesForAccountDiskOfferingIdsAndNotForVms(long accountId, List<Long> diskOfferingIds, List<Long> vmIds) {
SearchBuilder<VolumeVO> sb = createSearchBuilder();
sb.and("account", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.and("state", sb.entity().getState(), SearchCriteria.Op.NIN);
sb.and("diskOfferingIds", sb.entity().getDiskOfferingId(), SearchCriteria.Op.IN);
sb.and("displayVolume", sb.entity().isDisplayVolume(), Op.EQ);
if (CollectionUtils.isNotEmpty(vmIds)) {
sb.and().op("instanceId", sb.entity().getInstanceId(), Op.NULL);
sb.or("notVmIds", sb.entity().getInstanceId(), Op.NIN);
sb.cp();
}
sb.done();
SearchCriteria<VolumeVO> sc = sb.create();
sc.setParameters("account", accountId);
sc.setParameters("state", Volume.State.Destroy, Volume.State.Expunged);
sc.setParameters("diskOfferingIds", diskOfferingIds.toArray());
sc.setParameters("displayVolume", 1);
if (CollectionUtils.isNotEmpty(vmIds)) {
sc.setParameters("notVmIds", vmIds.toArray());
}
return listBy(sc);
}
}

View File

@ -30,6 +30,7 @@ import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
@ -329,17 +330,7 @@ public class NicVO implements Nic {
@Override
public String toString() {
return new StringBuilder("Nic[").append(id)
.append("-")
.append(instanceId)
.append("-")
.append(deviceId)
.append("-")
.append(reservationId)
.append("-")
.append(iPv4Address)
.append("]")
.toString();
return String.format("Nic %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "instanceId", "deviceId", "broadcastUri", "reservationId", "iPv4Address"));
}
@Override

View File

@ -18,10 +18,6 @@
//
package org.apache.cloudstack.reservation;
import com.cloud.configuration.Resource;
import org.apache.cloudstack.user.ResourceReservation;
import com.cloud.utils.exception.CloudRuntimeException;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
@ -29,6 +25,11 @@ import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.apache.cloudstack.user.ResourceReservation;
import com.cloud.configuration.Resource;
import com.cloud.utils.exception.CloudRuntimeException;
@Entity
@Table(name = "resource_reservation")
public class ReservationVO implements ResourceReservation {
@ -47,22 +48,30 @@ public class ReservationVO implements ResourceReservation {
@Column(name = "resource_type", nullable = false)
Resource.ResourceType resourceType;
@Column(name = "tag")
String tag;
@Column(name = "amount")
long amount;
protected ReservationVO()
{}
protected ReservationVO() {
}
public ReservationVO(Long accountId, Long domainId, Resource.ResourceType resourceType, Long delta) {
public ReservationVO(Long accountId, Long domainId, Resource.ResourceType resourceType, String tag, Long delta) {
if (delta == null || delta <= 0) {
throw new CloudRuntimeException("resource reservations can not be made for no resources");
}
this.accountId = accountId;
this.domainId = domainId;
this.resourceType = resourceType;
this.tag = tag;
this.amount = delta;
}
public ReservationVO(Long accountId, Long domainId, Resource.ResourceType resourceType, Long delta) {
this(accountId, domainId, resourceType, null, delta);
}
@Override
public long getId() {
return this.id;
@ -83,6 +92,11 @@ public class ReservationVO implements ResourceReservation {
return resourceType;
}
@Override
public String getTag() {
return tag;
}
@Override
public Long getReservedAmount() {
return amount;

View File

@ -18,11 +18,12 @@
//
package org.apache.cloudstack.reservation.dao;
import com.cloud.configuration.Resource;
import org.apache.cloudstack.reservation.ReservationVO;
import com.cloud.configuration.Resource;
import com.cloud.utils.db.GenericDao;
public interface ReservationDao extends GenericDao<ReservationVO, Long> {
long getAccountReservation(Long account, Resource.ResourceType resourceType);
long getDomainReservation(Long domain, Resource.ResourceType resourceType);
long getAccountReservation(Long account, Resource.ResourceType resourceType, String tag);
long getDomainReservation(Long domain, Resource.ResourceType resourceType, String tag);
}

View File

@ -18,41 +18,63 @@
//
package org.apache.cloudstack.reservation.dao;
import java.util.List;
import org.apache.cloudstack.reservation.ReservationVO;
import com.cloud.configuration.Resource;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import org.apache.cloudstack.reservation.ReservationVO;
import java.util.List;
public class ReservationDaoImpl extends GenericDaoBase<ReservationVO, Long> implements ReservationDao {
private static final String RESOURCE_TYPE = "resourceType";
private static final String RESOURCE_TAG = "resourceTag";
private static final String ACCOUNT_ID = "accountId";
private static final String DOMAIN_ID = "domainId";
private final SearchBuilder<ReservationVO> listAccountAndTypeSearch;
private final SearchBuilder<ReservationVO> listAccountAndTypeAndNoTagSearch;
private final SearchBuilder<ReservationVO> listDomainAndTypeSearch;
private final SearchBuilder<ReservationVO> listDomainAndTypeAndNoTagSearch;
public ReservationDaoImpl() {
listAccountAndTypeSearch = createSearchBuilder();
listAccountAndTypeSearch.and(ACCOUNT_ID, listAccountAndTypeSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
listAccountAndTypeSearch.and(RESOURCE_TYPE, listAccountAndTypeSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
listAccountAndTypeSearch.and(RESOURCE_TAG, listAccountAndTypeSearch.entity().getTag(), SearchCriteria.Op.EQ);
listAccountAndTypeSearch.done();
listAccountAndTypeAndNoTagSearch = createSearchBuilder();
listAccountAndTypeAndNoTagSearch.and(ACCOUNT_ID, listAccountAndTypeAndNoTagSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
listAccountAndTypeAndNoTagSearch.and(RESOURCE_TYPE, listAccountAndTypeAndNoTagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
listAccountAndTypeAndNoTagSearch.and(RESOURCE_TAG, listAccountAndTypeAndNoTagSearch.entity().getTag(), SearchCriteria.Op.NULL);
listAccountAndTypeAndNoTagSearch.done();
listDomainAndTypeSearch = createSearchBuilder();
listDomainAndTypeSearch.and(DOMAIN_ID, listDomainAndTypeSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
listDomainAndTypeSearch.and(RESOURCE_TYPE, listDomainAndTypeSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
listDomainAndTypeSearch.and(RESOURCE_TAG, listDomainAndTypeSearch.entity().getTag(), SearchCriteria.Op.EQ);
listDomainAndTypeSearch.done();
listDomainAndTypeAndNoTagSearch = createSearchBuilder();
listDomainAndTypeAndNoTagSearch.and(ACCOUNT_ID, listDomainAndTypeAndNoTagSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
listDomainAndTypeAndNoTagSearch.and(RESOURCE_TYPE, listDomainAndTypeAndNoTagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
listDomainAndTypeAndNoTagSearch.and(RESOURCE_TAG, listDomainAndTypeAndNoTagSearch.entity().getTag(), SearchCriteria.Op.NULL);
listDomainAndTypeAndNoTagSearch.done();
}
@Override
public long getAccountReservation(Long accountId, Resource.ResourceType resourceType) {
public long getAccountReservation(Long accountId, Resource.ResourceType resourceType, String tag) {
long total = 0;
SearchCriteria<ReservationVO> sc = listAccountAndTypeSearch.create();
SearchCriteria<ReservationVO> sc = tag == null ?
listAccountAndTypeAndNoTagSearch.create() : listAccountAndTypeSearch.create();
sc.setParameters(ACCOUNT_ID, accountId);
sc.setParameters(RESOURCE_TYPE, resourceType);
if (tag != null) {
sc.setParameters(RESOURCE_TAG, tag);
}
List<ReservationVO> reservations = listBy(sc);
for (ReservationVO reservation : reservations) {
total += reservation.getReservedAmount();
@ -61,11 +83,15 @@ public class ReservationDaoImpl extends GenericDaoBase<ReservationVO, Long> impl
}
@Override
public long getDomainReservation(Long domainId, Resource.ResourceType resourceType) {
public long getDomainReservation(Long domainId, Resource.ResourceType resourceType, String tag) {
long total = 0;
SearchCriteria<ReservationVO> sc = listDomainAndTypeSearch.create();
SearchCriteria<ReservationVO> sc = tag == null ?
listDomainAndTypeAndNoTagSearch.create() : listDomainAndTypeSearch.create();
sc.setParameters(DOMAIN_ID, domainId);
sc.setParameters(RESOURCE_TYPE, resourceType);
if (tag != null) {
sc.setParameters(RESOURCE_TAG, tag);
}
List<ReservationVO> reservations = listBy(sc);
for (ReservationVO reservation : reservations) {
total += reservation.getReservedAmount();

View File

@ -40,6 +40,8 @@ public interface PrimaryDataStoreDao extends GenericDao<StoragePoolVO, Long> {
*/
List<StoragePoolVO> listBy(long datacenterId, Long podId, Long clusterId, ScopeType scope);
List<StoragePoolVO> listBy(long datacenterId, Long podId, Long clusterId, ScopeType scope, String keyword);
/**
* Set capacity of storage pool in bytes
* @param id pool id.
@ -115,15 +117,19 @@ public interface PrimaryDataStoreDao extends GenericDao<StoragePoolVO, Long> {
List<StoragePoolVO> findLocalStoragePoolsByTags(long dcId, long podId, Long clusterId, String[] tags, boolean validateTagRule);
List<StoragePoolVO> findLocalStoragePoolsByTags(long dcId, long podId, Long clusterId, String[] tags, boolean validateTagRule, String keyword);
List<StoragePoolVO> findZoneWideStoragePoolsByTags(long dcId, String[] tags, boolean validateTagRule);
List<StoragePoolVO> findZoneWideStoragePoolsByHypervisor(long dataCenterId, HypervisorType hypervisorType);
List<StoragePoolVO> findZoneWideStoragePoolsByHypervisor(long dataCenterId, HypervisorType hypervisorType, String keyword);
List<StoragePoolVO> findLocalStoragePoolsByHostAndTags(long hostId, String[] tags);
List<StoragePoolVO> listLocalStoragePoolByPath(long datacenterId, String path);
List<StoragePoolVO> findPoolsInClusters(List<Long> clusterIds);
List<StoragePoolVO> findPoolsInClusters(List<Long> clusterIds, String keyword);
void deletePoolTags(long poolId);

View File

@ -244,6 +244,11 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase<StoragePoolVO, Long>
@Override
public List<StoragePoolVO> listBy(long datacenterId, Long podId, Long clusterId, ScopeType scope) {
return listBy(datacenterId, podId, clusterId, scope, null);
}
@Override
public List<StoragePoolVO> listBy(long datacenterId, Long podId, Long clusterId, ScopeType scope, String keyword) {
SearchCriteria<StoragePoolVO> sc = null;
if (clusterId != null) {
sc = DcPodSearch.create();
@ -255,6 +260,9 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase<StoragePoolVO, Long>
sc.setParameters("datacenterId", datacenterId);
sc.setParameters("podId", podId);
sc.setParameters("status", Status.Up);
if (keyword != null) {
sc.addAnd("name", Op.LIKE, "%" + keyword + "%");
}
if (scope != null) {
sc.setParameters("scope", scope);
}
@ -444,9 +452,14 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase<StoragePoolVO, Long>
@Override
public List<StoragePoolVO> findLocalStoragePoolsByTags(long dcId, long podId, Long clusterId, String[] tags, boolean validateTagRule) {
return findLocalStoragePoolsByTags(dcId, podId, clusterId, tags, validateTagRule, null);
}
@Override
public List<StoragePoolVO> findLocalStoragePoolsByTags(long dcId, long podId, Long clusterId, String[] tags, boolean validateTagRule, String keyword) {
List<StoragePoolVO> storagePools = null;
if (tags == null || tags.length == 0) {
storagePools = listBy(dcId, podId, clusterId, ScopeType.HOST);
storagePools = listBy(dcId, podId, clusterId, ScopeType.HOST, keyword);
if (validateTagRule) {
storagePools = getPoolsWithoutTagRule(storagePools);
@ -583,11 +596,19 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase<StoragePoolVO, Long>
@Override
public List<StoragePoolVO> findZoneWideStoragePoolsByHypervisor(long dataCenterId, HypervisorType hypervisorType) {
return findZoneWideStoragePoolsByHypervisor(dataCenterId, hypervisorType, null);
}
@Override
public List<StoragePoolVO> findZoneWideStoragePoolsByHypervisor(long dataCenterId, HypervisorType hypervisorType, String keyword) {
QueryBuilder<StoragePoolVO> sc = QueryBuilder.create(StoragePoolVO.class);
sc.and(sc.entity().getDataCenterId(), Op.EQ, dataCenterId);
sc.and(sc.entity().getStatus(), Op.EQ, Status.Up);
sc.and(sc.entity().getScope(), Op.EQ, ScopeType.ZONE);
sc.and(sc.entity().getHypervisor(), Op.EQ, hypervisorType);
if (keyword != null) {
sc.and(sc.entity().getName(), Op.LIKE, "%" + keyword + "%");
}
return sc.list();
}
@ -612,10 +633,13 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase<StoragePoolVO, Long>
}
@Override
public List<StoragePoolVO> findPoolsInClusters(List<Long> clusterIds) {
public List<StoragePoolVO> findPoolsInClusters(List<Long> clusterIds, String keyword) {
SearchCriteria<StoragePoolVO> sc = ClustersSearch.create();
sc.setParameters("clusterIds", clusterIds.toArray());
sc.setParameters("status", StoragePoolStatus.Up);
if (keyword != null) {
sc.addAnd("name", Op.LIKE, "%" + keyword + "%");
}
return listBy(sc);
}

View File

@ -18,3 +18,13 @@
--;
-- Schema upgrade from 4.19.0.0 to 4.20.0.0
--;
-- Add tag column to tables
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.resource_limit', 'tag', 'varchar(64) DEFAULT NULL COMMENT "tag for the limit" ');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.resource_count', 'tag', 'varchar(64) DEFAULT NULL COMMENT "tag for the resource count" ');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.resource_reservation', 'tag', 'varchar(64) DEFAULT NULL COMMENT "tag for the resource reservation" ');
ALTER TABLE `resource_count`
DROP INDEX `i_resource_count__type_accountId`,
DROP INDEX `i_resource_count__type_domaintId`,
ADD UNIQUE INDEX `i_resource_count__type_tag_accountId` (`type`,`tag`,`account_id`),
ADD UNIQUE INDEX `i_resource_count__type_tag_domaintId` (`type`,`tag`,`domain_id`);

View File

@ -0,0 +1,164 @@
-- 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.
-- VIEW `cloud`.`account_view`;
DROP VIEW IF EXISTS `cloud`.`account_view`;
CREATE VIEW `cloud`.`account_view` AS
select
`account`.`id` AS `id`,
`account`.`uuid` AS `uuid`,
`account`.`account_name` AS `account_name`,
`account`.`type` AS `type`,
`account`.`role_id` AS `role_id`,
`account`.`state` AS `state`,
`account`.`created` AS `created`,
`account`.`removed` AS `removed`,
`account`.`cleanup_needed` AS `cleanup_needed`,
`account`.`network_domain` AS `network_domain` ,
`account`.`default` AS `default`,
`domain`.`id` AS `domain_id`,
`domain`.`uuid` AS `domain_uuid`,
`domain`.`name` AS `domain_name`,
`domain`.`path` AS `domain_path`,
`data_center`.`id` AS `data_center_id`,
`data_center`.`uuid` AS `data_center_uuid`,
`data_center`.`name` AS `data_center_name`,
`account_netstats_view`.`bytesReceived` AS `bytesReceived`,
`account_netstats_view`.`bytesSent` AS `bytesSent`,
`vmlimit`.`max` AS `vmLimit`,
`vmcount`.`count` AS `vmTotal`,
`runningvm`.`vmcount` AS `runningVms`,
`stoppedvm`.`vmcount` AS `stoppedVms`,
`iplimit`.`max` AS `ipLimit`,
`ipcount`.`count` AS `ipTotal`,
`free_ip_view`.`free_ip` AS `ipFree`,
`volumelimit`.`max` AS `volumeLimit`,
`volumecount`.`count` AS `volumeTotal`,
`snapshotlimit`.`max` AS `snapshotLimit`,
`snapshotcount`.`count` AS `snapshotTotal`,
`templatelimit`.`max` AS `templateLimit`,
`templatecount`.`count` AS `templateTotal`,
`vpclimit`.`max` AS `vpcLimit`,
`vpccount`.`count` AS `vpcTotal`,
`projectlimit`.`max` AS `projectLimit`,
`projectcount`.`count` AS `projectTotal`,
`networklimit`.`max` AS `networkLimit`,
`networkcount`.`count` AS `networkTotal`,
`cpulimit`.`max` AS `cpuLimit`,
`cpucount`.`count` AS `cpuTotal`,
`memorylimit`.`max` AS `memoryLimit`,
`memorycount`.`count` AS `memoryTotal`,
`primary_storage_limit`.`max` AS `primaryStorageLimit`,
`primary_storage_count`.`count` AS `primaryStorageTotal`,
`secondary_storage_limit`.`max` AS `secondaryStorageLimit`,
`secondary_storage_count`.`count` AS `secondaryStorageTotal`,
`async_job`.`id` AS `job_id`,
`async_job`.`uuid` AS `job_uuid`,
`async_job`.`job_status` AS `job_status`,
`async_job`.`account_id` AS `job_account_id`
from
`cloud`.`free_ip_view`,
`cloud`.`account`
inner join
`cloud`.`domain` ON account.domain_id = domain.id
left join
`cloud`.`data_center` ON account.default_zone_id = data_center.id
left join
`cloud`.`account_netstats_view` ON account.id = account_netstats_view.account_id
left join
`cloud`.`resource_limit` vmlimit ON account.id = vmlimit.account_id
and vmlimit.type = 'user_vm' and vmlimit.tag IS NULL
left join
`cloud`.`resource_count` vmcount ON account.id = vmcount.account_id
and vmcount.type = 'user_vm' and vmcount.tag IS NULL
left join
`cloud`.`account_vmstats_view` runningvm ON account.id = runningvm.account_id
and runningvm.state = 'Running'
left join
`cloud`.`account_vmstats_view` stoppedvm ON account.id = stoppedvm.account_id
and stoppedvm.state = 'Stopped'
left join
`cloud`.`resource_limit` iplimit ON account.id = iplimit.account_id
and iplimit.type = 'public_ip'
left join
`cloud`.`resource_count` ipcount ON account.id = ipcount.account_id
and ipcount.type = 'public_ip'
left join
`cloud`.`resource_limit` volumelimit ON account.id = volumelimit.account_id
and volumelimit.type = 'volume' and volumelimit.tag IS NULL
left join
`cloud`.`resource_count` volumecount ON account.id = volumecount.account_id
and volumecount.type = 'volume' and volumecount.tag IS NULL
left join
`cloud`.`resource_limit` snapshotlimit ON account.id = snapshotlimit.account_id
and snapshotlimit.type = 'snapshot'
left join
`cloud`.`resource_count` snapshotcount ON account.id = snapshotcount.account_id
and snapshotcount.type = 'snapshot'
left join
`cloud`.`resource_limit` templatelimit ON account.id = templatelimit.account_id
and templatelimit.type = 'template'
left join
`cloud`.`resource_count` templatecount ON account.id = templatecount.account_id
and templatecount.type = 'template'
left join
`cloud`.`resource_limit` vpclimit ON account.id = vpclimit.account_id
and vpclimit.type = 'vpc'
left join
`cloud`.`resource_count` vpccount ON account.id = vpccount.account_id
and vpccount.type = 'vpc'
left join
`cloud`.`resource_limit` projectlimit ON account.id = projectlimit.account_id
and projectlimit.type = 'project'
left join
`cloud`.`resource_count` projectcount ON account.id = projectcount.account_id
and projectcount.type = 'project'
left join
`cloud`.`resource_limit` networklimit ON account.id = networklimit.account_id
and networklimit.type = 'network'
left join
`cloud`.`resource_count` networkcount ON account.id = networkcount.account_id
and networkcount.type = 'network'
left join
`cloud`.`resource_limit` cpulimit ON account.id = cpulimit.account_id
and cpulimit.type = 'cpu' and cpulimit.tag IS NULL
left join
`cloud`.`resource_count` cpucount ON account.id = cpucount.account_id
and cpucount.type = 'cpu' and cpucount.tag IS NULL
left join
`cloud`.`resource_limit` memorylimit ON account.id = memorylimit.account_id
and memorylimit.type = 'memory' and memorylimit.tag IS NULL
left join
`cloud`.`resource_count` memorycount ON account.id = memorycount.account_id
and memorycount.type = 'memory' and memorycount.tag IS NULL
left join
`cloud`.`resource_limit` primary_storage_limit ON account.id = primary_storage_limit.account_id
and primary_storage_limit.type = 'primary_storage' and primary_storage_limit.tag IS NULL
left join
`cloud`.`resource_count` primary_storage_count ON account.id = primary_storage_count.account_id
and primary_storage_count.type = 'primary_storage' and primary_storage_count.tag IS NULL
left join
`cloud`.`resource_limit` secondary_storage_limit ON account.id = secondary_storage_limit.account_id
and secondary_storage_limit.type = 'secondary_storage'
left join
`cloud`.`resource_count` secondary_storage_count ON account.id = secondary_storage_count.account_id
and secondary_storage_count.type = 'secondary_storage'
left join
`cloud`.`async_job` ON async_job.instance_id = account.id
and async_job.instance_type = 'Account'
and async_job.job_status = 0;

View File

@ -0,0 +1,134 @@
-- 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.
-- VIEW `cloud`.`domain_view`;
DROP VIEW IF EXISTS `cloud`.`domain_view`;
CREATE VIEW `cloud`.`domain_view` AS
select
`domain`.`id` AS `id`,
`domain`.`parent` AS `parent`,
`domain`.`name` AS `name`,
`domain`.`uuid` AS `uuid`,
`domain`.`owner` AS `owner`,
`domain`.`path` AS `path`,
`domain`.`level` AS `level`,
`domain`.`child_count` AS `child_count`,
`domain`.`next_child_seq` AS `next_child_seq`,
`domain`.`created` AS `created`,
`domain`.`removed` AS `removed`,
`domain`.`state` AS `state`,
`domain`.`network_domain` AS `network_domain`,
`domain`.`type` AS `type`,
`vmlimit`.`max` AS `vmLimit`,
`vmcount`.`count` AS `vmTotal`,
`iplimit`.`max` AS `ipLimit`,
`ipcount`.`count` AS `ipTotal`,
`volumelimit`.`max` AS `volumeLimit`,
`volumecount`.`count` AS `volumeTotal`,
`snapshotlimit`.`max` AS `snapshotLimit`,
`snapshotcount`.`count` AS `snapshotTotal`,
`templatelimit`.`max` AS `templateLimit`,
`templatecount`.`count` AS `templateTotal`,
`vpclimit`.`max` AS `vpcLimit`,
`vpccount`.`count` AS `vpcTotal`,
`projectlimit`.`max` AS `projectLimit`,
`projectcount`.`count` AS `projectTotal`,
`networklimit`.`max` AS `networkLimit`,
`networkcount`.`count` AS `networkTotal`,
`cpulimit`.`max` AS `cpuLimit`,
`cpucount`.`count` AS `cpuTotal`,
`memorylimit`.`max` AS `memoryLimit`,
`memorycount`.`count` AS `memoryTotal`,
`primary_storage_limit`.`max` AS `primaryStorageLimit`,
`primary_storage_count`.`count` AS `primaryStorageTotal`,
`secondary_storage_limit`.`max` AS `secondaryStorageLimit`,
`secondary_storage_count`.`count` AS `secondaryStorageTotal`
from
`cloud`.`domain`
left join
`cloud`.`resource_limit` vmlimit ON domain.id = vmlimit.domain_id
and vmlimit.type = 'user_vm' and vmlimit.tag IS NULL
left join
`cloud`.`resource_count` vmcount ON domain.id = vmcount.domain_id
and vmcount.type = 'user_vm' and vmcount.tag IS NULL
left join
`cloud`.`resource_limit` iplimit ON domain.id = iplimit.domain_id
and iplimit.type = 'public_ip'
left join
`cloud`.`resource_count` ipcount ON domain.id = ipcount.domain_id
and ipcount.type = 'public_ip'
left join
`cloud`.`resource_limit` volumelimit ON domain.id = volumelimit.domain_id
and volumelimit.type = 'volume' and volumelimit.tag IS NULL
left join
`cloud`.`resource_count` volumecount ON domain.id = volumecount.domain_id
and volumecount.type = 'volume' and volumecount.tag IS NULL
left join
`cloud`.`resource_limit` snapshotlimit ON domain.id = snapshotlimit.domain_id
and snapshotlimit.type = 'snapshot'
left join
`cloud`.`resource_count` snapshotcount ON domain.id = snapshotcount.domain_id
and snapshotcount.type = 'snapshot'
left join
`cloud`.`resource_limit` templatelimit ON domain.id = templatelimit.domain_id
and templatelimit.type = 'template'
left join
`cloud`.`resource_count` templatecount ON domain.id = templatecount.domain_id
and templatecount.type = 'template'
left join
`cloud`.`resource_limit` vpclimit ON domain.id = vpclimit.domain_id
and vpclimit.type = 'vpc'
left join
`cloud`.`resource_count` vpccount ON domain.id = vpccount.domain_id
and vpccount.type = 'vpc'
left join
`cloud`.`resource_limit` projectlimit ON domain.id = projectlimit.domain_id
and projectlimit.type = 'project'
left join
`cloud`.`resource_count` projectcount ON domain.id = projectcount.domain_id
and projectcount.type = 'project'
left join
`cloud`.`resource_limit` networklimit ON domain.id = networklimit.domain_id
and networklimit.type = 'network'
left join
`cloud`.`resource_count` networkcount ON domain.id = networkcount.domain_id
and networkcount.type = 'network'
left join
`cloud`.`resource_limit` cpulimit ON domain.id = cpulimit.domain_id
and cpulimit.type = 'cpu' and cpulimit.tag IS NULL
left join
`cloud`.`resource_count` cpucount ON domain.id = cpucount.domain_id
and cpucount.type = 'cpu' and cpucount.tag IS NULL
left join
`cloud`.`resource_limit` memorylimit ON domain.id = memorylimit.domain_id
and memorylimit.type = 'memory' and memorylimit.tag IS NULL
left join
`cloud`.`resource_count` memorycount ON domain.id = memorycount.domain_id
and memorycount.type = 'memory' and memorycount.tag IS NULL
left join
`cloud`.`resource_limit` primary_storage_limit ON domain.id = primary_storage_limit.domain_id
and primary_storage_limit.type = 'primary_storage' and primary_storage_limit.tag IS NULL
left join
`cloud`.`resource_count` primary_storage_count ON domain.id = primary_storage_count.domain_id
and primary_storage_count.type = 'primary_storage' and primary_storage_count.tag IS NULL
left join
`cloud`.`resource_limit` secondary_storage_limit ON domain.id = secondary_storage_limit.domain_id
and secondary_storage_limit.type = 'secondary_storage'
left join
`cloud`.`resource_count` secondary_storage_count ON domain.id = secondary_storage_count.domain_id
and secondary_storage_count.type = 'secondary_storage';

View File

@ -1,84 +1,126 @@
// 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.host;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.vm.VirtualMachine;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.Before;
public class HostVOTest {
HostVO host;
ServiceOfferingVO offering;
@Before
public void setUp() throws Exception {
host = new HostVO();
offering = new ServiceOfferingVO("TestSO", 0, 0, 0, 0, 0,
false, "TestSO", false,VirtualMachine.Type.User,false);
}
@Test
public void testNoSO() {
assertFalse(host.checkHostServiceOfferingTags(null));
}
@Test
public void testNoTag() {
assertTrue(host.checkHostServiceOfferingTags(offering));
}
@Test
public void testRightTag() {
host.setHostTags(Arrays.asList("tag1","tag2"), false);
offering.setHostTag("tag2,tag1");
assertTrue(host.checkHostServiceOfferingTags(offering));
}
@Test
public void testWrongTag() {
host.setHostTags(Arrays.asList("tag1","tag2"), false);
offering.setHostTag("tag2,tag4");
assertFalse(host.checkHostServiceOfferingTags(offering));
}
@Test
public void checkHostServiceOfferingTagsTestRuleTagWithServiceTagThatMatches() {
host.setHostTags(List.of("tags[0] == 'A'"), true);
offering.setHostTag("A");
assertTrue(host.checkHostServiceOfferingTags(offering));
}
@Test
public void checkHostServiceOfferingTagsTestRuleTagWithServiceTagThatDoesNotMatch() {
host.setHostTags(List.of("tags[0] == 'A'"), true);
offering.setHostTag("B");
assertFalse(host.checkHostServiceOfferingTags(offering));
}
@Test
public void checkHostServiceOfferingTagsTestRuleTagWithNullServiceTag() {
host.setHostTags(List.of("tags[0] == 'A'"), true);
offering.setHostTag(null);
assertFalse(host.checkHostServiceOfferingTags(offering));
}
}
// 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.host;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.vm.VirtualMachine;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.Before;
import org.mockito.Mockito;
public class HostVOTest {
HostVO host;
ServiceOfferingVO offering;
@Before
public void setUp() throws Exception {
host = new HostVO();
offering = new ServiceOfferingVO("TestSO", 0, 0, 0, 0, 0,
false, "TestSO", false,VirtualMachine.Type.User,false);
}
@Test
public void testNoSO() {
assertFalse(host.checkHostServiceOfferingTags(null));
}
@Test
public void testNoTag() {
assertTrue(host.checkHostServiceOfferingTags(offering));
}
@Test
public void testRightTag() {
host.setHostTags(Arrays.asList("tag1","tag2"), false);
offering.setHostTag("tag2,tag1");
assertTrue(host.checkHostServiceOfferingTags(offering));
}
@Test
public void testWrongTag() {
host.setHostTags(Arrays.asList("tag1","tag2"), false);
offering.setHostTag("tag2,tag4");
assertFalse(host.checkHostServiceOfferingTags(offering));
}
@Test
public void checkHostServiceOfferingTagsTestRuleTagWithServiceTagThatMatches() {
host.setHostTags(List.of("tags[0] == 'A'"), true);
offering.setHostTag("A");
assertTrue(host.checkHostServiceOfferingTags(offering));
}
@Test
public void checkHostServiceOfferingTagsTestRuleTagWithServiceTagThatDoesNotMatch() {
host.setHostTags(List.of("tags[0] == 'A'"), true);
offering.setHostTag("B");
assertFalse(host.checkHostServiceOfferingTags(offering));
}
@Test
public void checkHostServiceOfferingTagsTestRuleTagWithNullServiceTag() {
host.setHostTags(List.of("tags[0] == 'A'"), true);
offering.setHostTag(null);
assertFalse(host.checkHostServiceOfferingTags(offering));
}
@Test
public void testEitherNoSOOrTemplate() {
assertFalse(host.checkHostServiceOfferingAndTemplateTags(null, Mockito.mock(VirtualMachineTemplate.class)));
assertFalse(host.checkHostServiceOfferingAndTemplateTags(Mockito.mock(ServiceOffering.class), null));
}
@Test
public void testNoTagOfferingTemplate() {
assertTrue(host.checkHostServiceOfferingAndTemplateTags(offering, Mockito.mock(VirtualMachineTemplate.class)));
}
@Test
public void testRightTagOfferingTemplate() {
host.setHostTags(Arrays.asList("tag1", "tag2"), false);
offering.setHostTag("tag2,tag1");
assertTrue(host.checkHostServiceOfferingAndTemplateTags(offering, Mockito.mock(VirtualMachineTemplate.class)));
host.setHostTags(Arrays.asList("tag1", "tag2", "tag3"), false);
offering.setHostTag("tag2,tag1");
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
Mockito.when(template.getTemplateTag()).thenReturn("tag3");
assertTrue(host.checkHostServiceOfferingAndTemplateTags(offering, template));
host.setHostTags(List.of("tag3"), false);
offering.setHostTag(null);
assertTrue(host.checkHostServiceOfferingAndTemplateTags(offering, template));
}
@Test
public void testWrongOfferingTag() {
host.setHostTags(Arrays.asList("tag1","tag2"), false);
offering.setHostTag("tag2,tag4");
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
Mockito.when(template.getTemplateTag()).thenReturn("tag1");
assertFalse(host.checkHostServiceOfferingAndTemplateTags(offering, template));
offering.setHostTag("tag1,tag2");
template = Mockito.mock(VirtualMachineTemplate.class);
Mockito.when(template.getTemplateTag()).thenReturn("tag3");
assertFalse(host.checkHostServiceOfferingAndTemplateTags(offering, template));
}
}

View File

@ -104,16 +104,20 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
return false;
}
protected abstract List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck);
protected abstract List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck, String keyword);
@Override
public List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo) {
return allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo, false);
return allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo, false, null);
}
@Override
public List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) {
List<StoragePool> pools = select(dskCh, vmProfile, plan, avoid, returnUpTo, bypassStorageTypeCheck);
return allocateToPool(dskCh, vmProfile, plan, avoid, returnUpTo, bypassStorageTypeCheck, null);
}
public List<StoragePool> allocateToPool(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck, String keyword) {
List<StoragePool> pools = select(dskCh, vmProfile, plan, avoid, returnUpTo, bypassStorageTypeCheck, keyword);
return reorderPools(pools, vmProfile, plan, dskCh);
}
@ -304,10 +308,14 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
return false;
}
Volume volume = volumeDao.findById(dskCh.getVolumeId());
if(!storageMgr.storagePoolCompatibleWithVolumePool(pool, volume)) {
logger.debug(String.format("Pool [%s] is not compatible with volume [%s], skipping it.", pool, volume));
return false;
Volume volume = null;
boolean isTempVolume = dskCh.getVolumeId() == Volume.DISK_OFFERING_SUITABILITY_CHECK_VOLUME_ID;
if (!isTempVolume) {
volume = volumeDao.findById(dskCh.getVolumeId());
if (!storageMgr.storagePoolCompatibleWithVolumePool(pool, volume)) {
logger.debug(String.format("Pool [%s] is not compatible with volume [%s], skipping it.", pool, volume));
return false;
}
}
if (pool.isManaged() && !storageUtil.managedStoragePoolCanScale(pool, plan.getClusterId(), plan.getHostId())) {
@ -332,8 +340,10 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
}
try {
boolean isStoragePoolStoragepolicyComplaince = storageMgr.isStoragePoolCompliantWithStoragePolicy(requestVolumeDiskProfilePairs, pool);
if (!isStoragePoolStoragepolicyComplaince) {
boolean isStoragePoolStoragePolicyCompliance = isTempVolume ?
storageMgr.isStoragePoolCompliantWithStoragePolicy(dskCh.getDiskOfferingId(), pool) :
storageMgr.isStoragePoolCompliantWithStoragePolicy(requestVolumeDiskProfilePairs, pool);
if (!isStoragePoolStoragePolicyCompliance) {
logger.debug(String.format("Skipping allocation of pool [%s] to volume [%s] because this pool is not compliant with the storage policy required by the volume.", pool, volume));
return false;
}
@ -342,7 +352,11 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
return false;
}
}
return storageMgr.storagePoolHasEnoughIops(requestVolumeDiskProfilePairs, pool) && storageMgr.storagePoolHasEnoughSpace(requestVolumeDiskProfilePairs, pool, plan.getClusterId());
return isTempVolume ?
(storageMgr.storagePoolHasEnoughIops(dskCh.getMinIops(), pool) &&
storageMgr.storagePoolHasEnoughSpace(dskCh.getSize(), pool)):
(storageMgr.storagePoolHasEnoughIops(requestVolumeDiskProfilePairs, pool) &&
storageMgr.storagePoolHasEnoughSpace(requestVolumeDiskProfilePairs, pool, plan.getClusterId()));
}
private boolean checkDiskProvisioningSupport(DiskProfile dskCh, StoragePool pool) {

View File

@ -44,7 +44,7 @@ public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocat
DiskOfferingDao _diskOfferingDao;
@Override
protected List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) {
protected List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck, String keyword) {
logStartOfSearch(dskCh, vmProfile, plan, returnUpTo, bypassStorageTypeCheck);
if (!bypassStorageTypeCheck && dskCh.useLocalStorage()) {

View File

@ -45,7 +45,7 @@ public class GarbageCollectingStoragePoolAllocator extends AbstractStoragePoolAl
boolean _storagePoolCleanupEnabled;
@Override
public List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) {
public List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck, String keyword) {
logStartOfSearch(dskCh, vmProfile, plan, returnUpTo, bypassStorageTypeCheck);
if (!_storagePoolCleanupEnabled) {
logger.debug("Storage pool cleanup is not enabled, so GarbageCollectingStoragePoolAllocator is being skipped.");

View File

@ -58,7 +58,7 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator {
ConfigurationDao _configDao;
@Override
protected List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) {
protected List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck, String keyword) {
logStartOfSearch(dskCh, vmProfile, plan, returnUpTo, bypassStorageTypeCheck);
if (!bypassStorageTypeCheck && !dskCh.useLocalStorage()) {
@ -99,7 +99,7 @@ public class LocalStoragePoolAllocator extends AbstractStoragePoolAllocator {
return null;
}
List<StoragePoolVO> availablePools =
storagePoolDao.findLocalStoragePoolsByTags(plan.getDataCenterId(), plan.getPodId(), plan.getClusterId(), dskCh.getTags(), true);
storagePoolDao.findLocalStoragePoolsByTags(plan.getDataCenterId(), plan.getPodId(), plan.getClusterId(), dskCh.getTags(), true, keyword);
availablePools.addAll(storagePoolJoinDao.findStoragePoolByScopeAndRuleTags(plan.getDataCenterId(), plan.getPodId(), plan.getClusterId(), ScopeType.HOST, List.of(dskCh.getTags())));
for (StoragePoolVO pool : availablePools) {
if (suitablePools.size() == returnUpTo) {

View File

@ -48,7 +48,7 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator {
private CapacityDao capacityDao;
@Override
protected List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) {
protected List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck, String keyword) {
logStartOfSearch(dskCh, vmProfile, plan, returnUpTo, bypassStorageTypeCheck);
if (!bypassStorageTypeCheck && dskCh.useLocalStorage()) {

View File

@ -137,7 +137,7 @@ public class AbstractStoragePoolAllocatorTest {
class MockStorapoolAllocater extends AbstractStoragePoolAllocator {
@Override
protected List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, DeploymentPlanner.ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) {
protected List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, DeploymentPlanner.ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck, String keyword) {
return null;
}
}

View File

@ -126,6 +126,7 @@ import com.cloud.storage.Volume;
import com.cloud.storage.Volume.State;
import com.cloud.storage.VolumeDetailVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VolumeDao;
@ -206,6 +207,8 @@ public class VolumeServiceImpl implements VolumeService {
private SnapshotApiService snapshotApiService;
@Inject
private PassphraseDao passphraseDao;
@Inject
private DiskOfferingDao diskOfferingDao;
public VolumeServiceImpl() {
}
@ -1610,8 +1613,7 @@ public class VolumeServiceImpl implements VolumeService {
if (vol.getAttachedVM() == null || vol.getAttachedVM().getType() == VirtualMachine.Type.User) {
// Decrement the resource count for volumes and primary storage belonging user VM's only
_resourceLimitMgr.decrementResourceCount(vol.getAccountId(), ResourceType.volume, vol.isDisplay());
_resourceLimitMgr.decrementResourceCount(vol.getAccountId(), ResourceType.primary_storage, vol.isDisplay(), new Long(vol.getSize()));
_resourceLimitMgr.decrementVolumeResourceCount(vol.getAccountId(), vol.isDisplay(), vol.getSize(), diskOfferingDao.findById(vol.getDiskOfferingId()));
}
}

View File

@ -22,9 +22,10 @@ import java.util.List;
import javax.inject.Inject;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import com.cloud.agent.manager.allocator.HostAllocator;
@ -39,8 +40,10 @@ import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.offering.ServiceOffering;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.VMTemplateVO;
import com.cloud.utils.Pair;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@ -57,6 +60,27 @@ public class RandomAllocator extends AdapterBase implements HostAllocator {
@Inject
private CapacityManager capacityManager;
protected List<HostVO> listHostsByTags(Host.Type type, long dcId, Long podId, Long clusterId, String offeringHostTag, String templateTag) {
List<HostVO> taggedHosts = new ArrayList<>();
if (offeringHostTag != null) {
taggedHosts.addAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, offeringHostTag));
}
if (templateTag != null) {
List<HostVO> templateTaggedHosts = _hostDao.listByHostTag(type, clusterId, podId, dcId, templateTag);
if (taggedHosts.isEmpty()) {
taggedHosts = templateTaggedHosts;
} else {
taggedHosts.retainAll(templateTaggedHosts);
}
}
if (logger.isDebugEnabled()) {
logger.debug(String.format("Found %d hosts %s with type: %s, zone ID: %d, pod ID: %d, cluster ID: %s, offering host tag(s): %s, template tag: %s",
taggedHosts.size(),
(taggedHosts.isEmpty() ? "" : String.format("(%s)", StringUtils.join(taggedHosts.stream().map(HostVO::getId).toArray(), ","))),
type.name(), dcId, podId, clusterId, offeringHostTag, templateTag));
}
return taggedHosts;
}
private List<Host> findSuitableHosts(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type,
ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
boolean considerReservedCapacity) {
@ -70,30 +94,34 @@ public class RandomAllocator extends AdapterBase implements HostAllocator {
if (type == Host.Type.Storage) {
return suitableHosts;
}
String hostTag = offering.getHostTag();
if (hostTag != null) {
logger.debug(String.format("Looking for hosts in dc [%s], pod [%s], cluster [%s] and complying with host tag [%s].", dcId, podId, clusterId, hostTag));
String offeringHostTag = offering.getHostTag();
VMTemplateVO template = (VMTemplateVO)vmProfile.getTemplate();
String templateTag = template.getTemplateTag();
String hostTag = null;
if (ObjectUtils.anyNull(offeringHostTag, templateTag)) {
hostTag = offeringHostTag;
hostTag = hostTag == null ? templateTag : String.format("%s, %s", hostTag, templateTag);
logger.debug(String.format("Looking for hosts in dc [%s], pod [%s], cluster [%s] and complying with host tag(s): [%s]", dcId, podId, clusterId, hostTag));
} else {
logger.debug("Looking for hosts in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId);
}
if (hosts != null) {
// retain all computing hosts, regardless of whether they support routing...it's random after all
hostsCopy = new ArrayList<Host>(hosts);
if (hostTag != null) {
hostsCopy.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, hostTag));
if (ObjectUtils.anyNotNull(offeringHostTag, templateTag)) {
hostsCopy.retainAll(listHostsByTags(type, dcId, podId, clusterId, offeringHostTag, templateTag));
} else {
hostsCopy.retainAll(_hostDao.listAllHostsThatHaveNoRuleTag(type, clusterId, podId, dcId));
}
} else {
// list all computing hosts, regardless of whether they support routing...it's random after all
hostsCopy = new ArrayList<HostVO>();
if (hostTag != null) {
hostsCopy = _hostDao.listByHostTag(type, clusterId, podId, dcId, hostTag);
if (offeringHostTag != null) {
hostsCopy = listHostsByTags(type, dcId, podId, clusterId, offeringHostTag, templateTag);
} else {
hostsCopy = _hostDao.listAllHostsThatHaveNoRuleTag(type, clusterId, podId, dcId);
}
}
hostsCopy = ListUtils.union(hostsCopy, _hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(hostTag));
hostsCopy = ListUtils.union(hostsCopy, _hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringHostTag));
if (hostsCopy.isEmpty()) {
logger.error(String.format("No suitable host found for vm [%s] with tags [%s].", vmProfile, hostTag));

View File

@ -0,0 +1,80 @@
// 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.agent.manager.allocator.impl;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
@RunWith(MockitoJUnitRunner.class)
public class RandomAllocatorTest {
@Mock
HostDao hostDao;
@InjectMocks
RandomAllocator randomAllocator;
@Test
public void testListHostsByTags() {
Host.Type type = Host.Type.Routing;
Long id = 1L;
String templateTag = "tag1";
String offeringTag = "tag2";
HostVO host1 = Mockito.mock(HostVO.class);
HostVO host2 = Mockito.mock(HostVO.class);
Mockito.when(hostDao.listByHostTag(type, id, id, id, offeringTag)).thenReturn(List.of(host1, host2));
// No template tagged host
Mockito.when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(new ArrayList<>());
List<HostVO> result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, templateTag);
Assert.assertTrue(CollectionUtils.isEmpty(result));
// Different template tagged host
HostVO host3 = Mockito.mock(HostVO.class);
Mockito.when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(List.of(host3));
result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, templateTag);
Assert.assertTrue(CollectionUtils.isEmpty(result));
// Matching template tagged host
Mockito.when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(List.of(host1));
result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, templateTag);
Assert.assertFalse(CollectionUtils.isEmpty(result));
Assert.assertEquals(1, result.size());
// No template tag
result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, null);
Assert.assertFalse(CollectionUtils.isEmpty(result));
Assert.assertEquals(2, result.size());
// No offering tag
result = randomAllocator.listHostsByTags(type, id, id, id, null, templateTag);
Assert.assertFalse(CollectionUtils.isEmpty(result));
Assert.assertEquals(1, result.size());
}
}

View File

@ -50,6 +50,7 @@ import com.cloud.agent.api.storage.ListTemplateCommand;
import com.cloud.agent.api.storage.ListVolumeCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.storage.ResizeVolumeCommand;
import com.cloud.utils.component.Manager;
public interface MockStorageManager extends Manager {
@ -113,4 +114,6 @@ public interface MockStorageManager extends Manager {
public UploadStatusAnswer getUploadStatus(UploadStatusCommand cmd);
Answer handleConfigDriveIso(HandleConfigDriveIsoCommand cmd);
Answer handleResizeVolume(ResizeVolumeCommand cmd);
}

View File

@ -78,6 +78,8 @@ import com.cloud.agent.api.storage.ListVolumeAnswer;
import com.cloud.agent.api.storage.ListVolumeCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.storage.ResizeVolumeAnswer;
import com.cloud.agent.api.storage.ResizeVolumeCommand;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.NfsTO;
import com.cloud.agent.api.to.StorageFilerTO;
@ -1307,4 +1309,32 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa
return new Answer(cmd);
}
@Override
public Answer handleResizeVolume(ResizeVolumeCommand cmd) {
Long currentSize = cmd.getCurrentSize();
Long newSize = cmd.getNewSize();
MockStoragePoolVO storagePool = null;
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.SIMULATOR_DB);
try {
txn.start();
storagePool = _mockStoragePoolDao.findByUuid(cmd.getPoolUuid());
txn.commit();
if (storagePool == null) {
return new ResizeVolumeAnswer(cmd, false, "Failed to find storage pool: " + cmd.getPoolUuid());
}
} catch (Exception ex) {
txn.rollback();
throw new CloudRuntimeException("Error when finding storage " + cmd.getPoolUuid(), ex);
} finally {
txn.close();
txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
txn.close();
}
if (newSize >= currentSize) {
return new ResizeVolumeAnswer(cmd, true, "", newSize);
}
return new ResizeVolumeAnswer(cmd, false, "Failed to resize");
}
}

View File

@ -114,6 +114,7 @@ import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.ListTemplateCommand;
import com.cloud.agent.api.storage.ListVolumeCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.storage.ResizeVolumeCommand;
import com.cloud.api.commands.CleanupSimulatorMockCmd;
import com.cloud.api.commands.ConfigureSimulatorCmd;
import com.cloud.api.commands.ConfigureSimulatorHAProviderState;
@ -440,6 +441,8 @@ public class SimulatorManagerImpl extends ManagerBase implements SimulatorManage
answer = _mockVmMgr.fence((FenceCommand)cmd);
} else if (cmd instanceof HandleConfigDriveIsoCommand) {
answer = _mockStorageMgr.handleConfigDriveIso((HandleConfigDriveIsoCommand)cmd);
} else if (cmd instanceof ResizeVolumeCommand) {
answer = _mockStorageMgr.handleResizeVolume((ResizeVolumeCommand)cmd);
} else if (cmd instanceof GetRouterAlertsCommand
|| cmd instanceof VpnUsersCfgCommand
|| cmd instanceof RemoteAccessVpnCfgCommand

View File

@ -25,15 +25,9 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
import com.cloud.configuration.dao.ResourceCountDao;
import com.cloud.dc.DedicatedResourceVO;
import com.cloud.dc.dao.DedicatedResourceDao;
import com.cloud.host.HostStats;
import com.cloud.host.HostTagVO;
import com.cloud.user.Account;
import com.cloud.user.dao.AccountDao;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.commons.lang3.StringUtils;
import com.cloud.alert.AlertManager;
import com.cloud.api.ApiDBUtils;
@ -43,16 +37,21 @@ import com.cloud.api.query.vo.DomainJoinVO;
import com.cloud.api.query.vo.StoragePoolJoinVO;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityManager;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.CapacityState;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.capacity.dao.CapacityDaoImpl;
import com.cloud.configuration.Resource;
import com.cloud.configuration.dao.ResourceCountDao;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.DedicatedResourceVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDao;
import com.cloud.dc.dao.DedicatedResourceDao;
import com.cloud.host.Host;
import com.cloud.host.HostStats;
import com.cloud.host.HostTagVO;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
@ -63,7 +62,8 @@ import com.cloud.storage.StorageStats;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VolumeDao;
import org.apache.commons.lang3.StringUtils;
import com.cloud.user.Account;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
@ -438,13 +438,13 @@ public class PrometheusExporterImpl extends ManagerBase implements PrometheusExp
}
long memoryUsed = _resourceCountDao.getResourceCount(domain.getId(), Resource.ResourceOwnerType.Domain,
Resource.ResourceType.memory);
Resource.ResourceType.memory, null);
long cpuUsed = _resourceCountDao.getResourceCount(domain.getId(), Resource.ResourceOwnerType.Domain,
Resource.ResourceType.cpu);
Resource.ResourceType.cpu, null);
long primaryStorageUsed = _resourceCountDao.getResourceCount(domain.getId(), Resource.ResourceOwnerType.Domain,
Resource.ResourceType.primary_storage);
Resource.ResourceType.primary_storage, null);
long secondaryStorageUsed = _resourceCountDao.getResourceCount(domain.getId(), Resource.ResourceOwnerType.Domain,
Resource.ResourceType.secondary_storage);
Resource.ResourceType.secondary_storage, null);
metricsList.add(new ItemPerDomainResourceCount(memoryUsed, domain.getPath(), Resource.ResourceType.memory.getName()));
metricsList.add(new ItemPerDomainResourceCount(cpuUsed, domain.getPath(), Resource.ResourceType.cpu.getName()));

View File

@ -33,7 +33,7 @@ import com.cloud.vm.VirtualMachineProfile;
public class RandomStoragePoolAllocator extends AbstractStoragePoolAllocator {
@Override
public List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck) {
public List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid, int returnUpTo, boolean bypassStorageTypeCheck, String keyword) {
logStartOfSearch(dskCh, vmProfile, plan, returnUpTo, bypassStorageTypeCheck);
List<StoragePool> suitablePools = new ArrayList<StoragePool>();

View File

@ -23,6 +23,7 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
@ -53,6 +54,7 @@ import org.apache.cloudstack.api.response.HostTagResponse;
import org.apache.cloudstack.api.response.ImageStoreResponse;
import org.apache.cloudstack.api.response.InstanceGroupResponse;
import org.apache.cloudstack.api.response.NetworkOfferingResponse;
import org.apache.cloudstack.api.response.ObjectStoreResponse;
import org.apache.cloudstack.api.response.ProjectAccountResponse;
import org.apache.cloudstack.api.response.ProjectInvitationResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
@ -85,6 +87,8 @@ import org.apache.cloudstack.framework.jobs.dao.AsyncJobDao;
import org.apache.cloudstack.resourcedetail.SnapshotPolicyDetailVO;
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
import org.apache.cloudstack.resourcedetail.dao.SnapshotPolicyDetailsDao;
import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao;
import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
@ -337,6 +341,7 @@ import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.VmStats;
import com.cloud.vm.dao.ConsoleProxyDao;
@ -350,10 +355,6 @@ import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.snapshot.VMSnapshot;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
import org.apache.cloudstack.api.response.ObjectStoreResponse;
import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao;
import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO;
public class ApiDBUtils {
private static ManagementServer s_ms;
static AsyncJobManager s_asyncMgr;
@ -489,6 +490,7 @@ public class ApiDBUtils {
static ObjectStoreDao s_objectStoreDao;
static BucketDao s_bucketDao;
static VirtualMachineManager s_virtualMachineManager;
@Inject
private ManagementServer ms;
@ -752,6 +754,8 @@ public class ApiDBUtils {
private ObjectStoreDao objectStoreDao;
@Inject
private BucketDao bucketDao;
@Inject
private VirtualMachineManager virtualMachineManager;
@PostConstruct
void init() {
@ -886,6 +890,7 @@ public class ApiDBUtils {
s_resourceManagerUtil = resourceManagerUtil;
s_objectStoreDao = objectStoreDao;
s_bucketDao = bucketDao;
s_virtualMachineManager = virtualMachineManager;
}
// ///////////////////////////////////////////////////////////
@ -937,7 +942,7 @@ public class ApiDBUtils {
return -1;
}
return s_resourceLimitMgr.findCorrectResourceLimitForDomain(domain, type);
return s_resourceLimitMgr.findCorrectResourceLimitForDomain(domain, type, null);
}
public static long findCorrectResourceLimitForDomain(Long limit, boolean isRootDomain, ResourceType type, long domainId) {
@ -954,16 +959,6 @@ public class ApiDBUtils {
}
}
public static long findCorrectResourceLimit(ResourceType type, long accountId) {
AccountVO account = s_accountDao.findById(accountId);
if (account == null) {
return -1;
}
return s_resourceLimitMgr.findCorrectResourceLimitForAccount(account, type);
}
public static long findCorrectResourceLimit(Long limit, long accountId, ResourceType type) {
return s_resourceLimitMgr.findCorrectResourceLimitForAccount(accountId, limit, type);
}
@ -984,7 +979,7 @@ public class ApiDBUtils {
return -1;
}
return s_resourceLimitMgr.getResourceCount(account, type);
return s_resourceLimitMgr.getResourceCount(account, type, null);
}
public static String getSecurityGroupsNamesForVm(long vmId) {
@ -2098,6 +2093,22 @@ public class ApiDBUtils {
return s_jobJoinDao.newAsyncJobView(e);
}
public static List<DiskOfferingResponse> newDiskOfferingResponses(Long vmId, List<DiskOfferingJoinVO> offerings) {
List<DiskOfferingResponse> list = new ArrayList<>();
Map<Long, Boolean> suitability = null;
if (vmId != null) {
suitability = s_virtualMachineManager.getDiskOfferingSuitabilityForVm(vmId, offerings.stream().map(DiskOfferingJoinVO::getId).collect(Collectors.toList()));
}
for (DiskOfferingJoinVO offering : offerings) {
DiskOfferingResponse response = s_diskOfferingJoinDao.newDiskOfferingResponse(offering);
if (vmId != null) {
response.setSuitableForVm(suitability.get(offering.getId()));
}
list.add(response);
}
return list;
}
public static DiskOfferingResponse newDiskOfferingResponse(DiskOfferingJoinVO offering) {
return s_diskOfferingJoinDao.newDiskOfferingResponse(offering);
}

View File

@ -564,6 +564,7 @@ public class ApiResponseHelper implements ResponseGenerator {
} else {
resourceLimitResponse.setMax(limit.getMax());
}
resourceLimitResponse.setTag(limit.getTag());
resourceLimitResponse.setObjectName("resourcelimit");
return resourceLimitResponse;
@ -585,7 +586,10 @@ public class ApiResponseHelper implements ResponseGenerator {
resourceCountResponse.setResourceType(resourceCount.getType());
resourceCountResponse.setResourceCount(resourceCount.getCount());
resourceCountResponse.setObjectName("resourcecount");
resourceCountResponse.setObjectName(ApiConstants.RESOURCE_COUNT);
if (StringUtils.isNotEmpty(resourceCount.getTag())) {
resourceCountResponse.setTag(resourceCount.getTag());
}
return resourceCountResponse;
}
@ -2015,6 +2019,21 @@ public class ApiResponseHelper implements ResponseGenerator {
return ApiDBUtils.newEventResponse(vEvent);
}
protected boolean capacityListingForSingleTag(List<? extends Capacity> capacities) {
String tag = capacities.get(0).getTag();
if (tag == null) {
return false;
}
List<? extends Capacity> taggedCapacities = capacities.stream().filter(x -> tag.equals(x.getTag())).collect(Collectors.toList());
return taggedCapacities.size() == capacities.size();
}
protected boolean capacityListingForSingleNonGpuType(List<? extends Capacity> capacities) {
short type = capacities.get(0).getCapacityType();
List<? extends Capacity> typeCapacities = capacities.stream().filter(x -> x.getCapacityType() == type).collect(Collectors.toList());
return typeCapacities.size() == capacities.size();
}
@Override
public List<CapacityResponse> createCapacityResponse(List<? extends Capacity> result, DecimalFormat format) {
List<CapacityResponse> capacityResponses = new ArrayList<CapacityResponse>();
@ -2060,13 +2079,18 @@ public class ApiResponseHelper implements ResponseGenerator {
} else {
capacityResponse.setPercentUsed(format.format(0L));
}
capacityResponse.setTag(summedCapacity.getTag());
capacityResponse.setObjectName("capacity");
capacityResponses.add(capacityResponse);
}
List<VgpuTypesInfo> gpuCapacities;
if (result.size() > 1 && (gpuCapacities = ApiDBUtils.getGpuCapacites(result.get(0).getDataCenterId(), result.get(0).getPodId(), result.get(0).getClusterId())) != null) {
if (result.size() > 1 &&
!capacityListingForSingleTag(result) &&
!capacityListingForSingleNonGpuType(result) &&
(gpuCapacities = ApiDBUtils.getGpuCapacites(result.get(0).getDataCenterId(),
result.get(0).getPodId(), result.get(0).getClusterId())) != null) {
HashMap<String, Long> vgpuVMs = ApiDBUtils.getVgpuVmsCount(result.get(0).getDataCenterId(), result.get(0).getPodId(), result.get(0).getClusterId());
float capacityUsed = 0;

View File

@ -281,6 +281,7 @@ import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.StoragePoolTagVO;
import com.cloud.storage.VMTemplateVO;
@ -521,6 +522,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Inject
private ResourceIconDao resourceIconDao;
@Inject
StorageManager storageManager;
@Inject
private ManagementServerHostDao msHostDao;
@ -3153,8 +3156,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override
public ListResponse<DiskOfferingResponse> searchForDiskOfferings(ListDiskOfferingsCmd cmd) {
Pair<List<DiskOfferingJoinVO>, Integer> result = searchForDiskOfferingsInternal(cmd);
ListResponse<DiskOfferingResponse> response = new ListResponse<DiskOfferingResponse>();
List<DiskOfferingResponse> offeringResponses = ViewResponseHelper.createDiskOfferingResponse(result.first().toArray(new DiskOfferingJoinVO[result.first().size()]));
ListResponse<DiskOfferingResponse> response = new ListResponse<>();
List<DiskOfferingResponse> offeringResponses = ViewResponseHelper.createDiskOfferingResponses(cmd.getVirtualMachineId(), result.first());
response.setResponses(offeringResponses, result.second());
return response;
}
@ -3189,6 +3192,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Long storagePoolId = cmd.getStoragePoolId();
Boolean encrypt = cmd.getEncrypt();
String storageType = cmd.getStorageType();
final Long vmId = cmd.getVirtualMachineId();
// Keeping this logic consistent with domain specific zones
// if a domainId is provided, we just return the disk offering
@ -3296,6 +3300,16 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.addAnd("domainId", SearchCriteria.Op.SC, scc);
}
if (vmId != null) {
UserVmVO vm = userVmDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException("Unable to find the VM instance with the specified ID");
}
if (!isRootAdmin) {
accountMgr.checkAccess(account, null, false, vm);
}
}
Pair<List<DiskOfferingJoinVO>, Integer> result = _diskOfferingJoinDao.searchAndCount(sc, searchFilter);
String[] requiredTagsArray = new String[0];
if (CollectionUtils.isNotEmpty(result.first()) && VolumeApiServiceImpl.MatchStoragePoolTagsWithDiskOffering.valueIn(zoneId)) {
@ -3354,6 +3368,24 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
return response;
}
protected List<String> getHostTagsFromTemplateForServiceOfferingsListing(Account caller, Long templateId) {
List<String> hostTags = new ArrayList<>();
if (templateId == null) {
return hostTags;
}
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(templateId);
if (template == null) {
throw new InvalidParameterValueException("Unable to find template with the specified ID");
}
if (caller.getType() != Account.Type.ADMIN) {
accountMgr.checkAccess(caller, null, false, template);
}
if (StringUtils.isNotEmpty(template.getTemplateTag())) {
hostTags.add(template.getTemplateTag());
}
return hostTags;
}
private Pair<List<ServiceOfferingJoinVO>, Integer> searchForServiceOfferingsInternal(ListServiceOfferingsCmd cmd) {
// Note
// The filteredOfferings method for offerings is being modified in accordance with
@ -3385,6 +3417,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Integer cpuSpeed = cmd.getCpuSpeed();
Boolean encryptRoot = cmd.getEncryptRoot();
String storageType = cmd.getStorageType();
final Long templateId = cmd.getTemplateId();
final Account owner = accountMgr.finalizeOwner(caller, accountName, domainId, projectId);
SearchCriteria<ServiceOfferingJoinVO> sc = _srvOfferingJoinDao.createSearchCriteria();
@ -3579,6 +3612,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.addAnd("domainId", SearchCriteria.Op.SC, scc);
}
List<String> hostTags = getHostTagsFromTemplateForServiceOfferingsListing(caller, templateId);
if (currentVmOffering != null) {
DiskOfferingVO diskOffering = _diskOfferingDao.findByIdIncludingRemoved(currentVmOffering.getDiskOfferingId());
List<String> storageTags = com.cloud.utils.StringUtils.csvTagsToList(diskOffering.getTags());
@ -3596,26 +3631,29 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.addAnd("storageTags", SearchCriteria.Op.SC, scc);
}
List<String> hostTags = com.cloud.utils.StringUtils.csvTagsToList(currentVmOffering.getHostTag());
if (!hostTags.isEmpty()) {
SearchBuilder<ServiceOfferingJoinVO> hostTagsSearchBuilder = _srvOfferingJoinDao.createSearchBuilder();
for(String tag : hostTags) {
hostTagsSearchBuilder.and(tag, hostTagsSearchBuilder.entity().getHostTag(), Op.FIND_IN_SET);
}
hostTagsSearchBuilder.done();
SearchCriteria<ServiceOfferingJoinVO> hostTagsSearchCriteria = hostTagsSearchBuilder.create();
for(String tag : hostTags) {
hostTagsSearchCriteria.setParameters(tag, tag);
}
SearchCriteria<ServiceOfferingJoinVO> finalHostTagsSearchCriteria = _srvOfferingJoinDao.createSearchCriteria();
finalHostTagsSearchCriteria.addOr("hostTag", Op.NULL);
finalHostTagsSearchCriteria.addOr("hostTag", Op.SC, hostTagsSearchCriteria);
sc.addAnd("hostTagsConstraint", SearchCriteria.Op.SC, finalHostTagsSearchCriteria);
List<String> offeringHostTags = com.cloud.utils.StringUtils.csvTagsToList(currentVmOffering.getHostTag());
if (!offeringHostTags.isEmpty()) {
hostTags.addAll(offeringHostTags);
}
}
if (CollectionUtils.isNotEmpty(hostTags)) {
SearchBuilder<ServiceOfferingJoinVO> hostTagsSearchBuilder = _srvOfferingJoinDao.createSearchBuilder();
for(String tag : hostTags) {
hostTagsSearchBuilder.and(tag, hostTagsSearchBuilder.entity().getHostTag(), Op.FIND_IN_SET);
}
hostTagsSearchBuilder.done();
SearchCriteria<ServiceOfferingJoinVO> hostTagsSearchCriteria = hostTagsSearchBuilder.create();
for(String tag : hostTags) {
hostTagsSearchCriteria.setParameters(tag, tag);
}
SearchCriteria<ServiceOfferingJoinVO> finalHostTagsSearchCriteria = _srvOfferingJoinDao.createSearchCriteria();
finalHostTagsSearchCriteria.addOr("hostTag", Op.NULL);
finalHostTagsSearchCriteria.addOr("hostTag", Op.SC, hostTagsSearchCriteria);
sc.addAnd("hostTagsConstraint", SearchCriteria.Op.SC, finalHostTagsSearchCriteria);
}
return _srvOfferingJoinDao.searchAndCount(sc, searchFilter);
}

View File

@ -557,12 +557,8 @@ public class ViewResponseHelper {
return respList;
}
public static List<DiskOfferingResponse> createDiskOfferingResponse(DiskOfferingJoinVO... offerings) {
List<DiskOfferingResponse> respList = new ArrayList<DiskOfferingResponse>();
for (DiskOfferingJoinVO vt : offerings) {
respList.add(ApiDBUtils.newDiskOfferingResponse(vt));
}
return respList;
public static List<DiskOfferingResponse> createDiskOfferingResponses(Long vmId, List<DiskOfferingJoinVO> offerings) {
return ApiDBUtils.newDiskOfferingResponses(vmId, offerings);
}
public static List<ServiceOfferingResponse> createServiceOfferingResponse(ServiceOfferingJoinVO... offerings) {

View File

@ -19,7 +19,6 @@ package com.cloud.api.query.dao;
import java.util.List;
import java.util.Set;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.response.UserVmResponse;
@ -28,6 +27,7 @@ import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import com.cloud.utils.db.GenericDao;
import com.cloud.vm.VirtualMachine;
public interface UserVmJoinDao extends GenericDao<UserVmJoinVO, Long> {
@ -43,4 +43,7 @@ public interface UserVmJoinDao extends GenericDao<UserVmJoinVO, Long> {
List<UserVmJoinVO> searchByIds(Long... ids);
List<UserVmJoinVO> listActiveByIsoId(Long isoId);
List<UserVmJoinVO> listByAccountServiceOfferingTemplateAndNotInState(long accountId, List<VirtualMachine.State> states,
List<Long> offeringIds, List<Long> templateIds);
}

View File

@ -43,6 +43,7 @@ import org.apache.cloudstack.api.response.VnfNicResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.query.QueryService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
@ -679,4 +680,30 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
return searchByIds(vmIdSet.toArray(new Long[vmIdSet.size()]));
}
@Override
public List<UserVmJoinVO> listByAccountServiceOfferingTemplateAndNotInState(long accountId, List<State> states,
List<Long> offeringIds, List<Long> templateIds) {
SearchBuilder<UserVmJoinVO> userVmSearch = createSearchBuilder();
userVmSearch.and("accountId", userVmSearch.entity().getAccountId(), Op.EQ);
userVmSearch.and("serviceOfferingId", userVmSearch.entity().getServiceOfferingId(), Op.IN);
userVmSearch.and("templateId", userVmSearch.entity().getTemplateId(), Op.IN);
userVmSearch.and("state", userVmSearch.entity().getState(), SearchCriteria.Op.NIN);
userVmSearch.and("displayVm", userVmSearch.entity().isDisplayVm(), Op.EQ);
userVmSearch.groupBy(userVmSearch.entity().getId()); // select distinct
userVmSearch.done();
SearchCriteria<UserVmJoinVO> sc = userVmSearch.create();
sc.setParameters("accountId", accountId);
if (CollectionUtils.isNotEmpty(offeringIds)) {
sc.setParameters("serviceOfferingId", offeringIds.toArray());
}
if (CollectionUtils.isNotEmpty(templateIds)) {
sc.setParameters("templateId", templateIds.toArray());
}
if (CollectionUtils.isNotEmpty(states)) {
sc.setParameters("state", states.toArray());
}
sc.setParameters("displayVm", 1);
return listBy(sc);
}
}

View File

@ -125,6 +125,7 @@ import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.AccountManager;
import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
@ -730,10 +731,11 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
protected boolean checkVmProfileAndHost(final VirtualMachineProfile vmProfile, final HostVO host) {
ServiceOffering offering = vmProfile.getServiceOffering();
if (offering.getHostTag() != null) {
VirtualMachineTemplate template = vmProfile.getTemplate();
if (offering.getHostTag() != null || template.getTemplateTag() != null) {
_hostDao.loadHostTags(host);
if (!host.checkHostServiceOfferingTags(offering)) {
logger.debug("Service Offering host tag does not match the last host of this VM");
if (!host.checkHostServiceOfferingAndTemplateTags(offering, template)) {
logger.debug("Service Offering host tag or template tag does not match the last host of this VM");
return false;
}
}

View File

@ -21,6 +21,7 @@ import java.util.Map;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.network.router.VirtualNetworkApplianceManager;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import com.cloud.configuration.Config;
@ -169,18 +170,24 @@ public class ControlNetworkGuru extends PodBasedNetworkGuru implements NetworkGu
assert nic.getTrafficType() == TrafficType.Control;
HypervisorType hType = vm.getHypervisorType();
if ( ( (hType == HypervisorType.VMware) || (hType == HypervisorType.Hyperv) )&& isRouterVm(vm)) {
if (!VirtualNetworkApplianceManager.RemoveControlIpOnStop.valueIn(vm.getVirtualMachine().getDataCenterId())) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("not releasing %s from %s with reservationId %s, as systemvm.release.control.ip.on.stop is set to false for the data center.", nic, vm, reservationId));
}
return true;
}
long dcId = vm.getVirtualMachine().getDataCenterId();
DataCenterVO dcVo = _dcDao.findById(dcId);
if (dcVo.getNetworkType() != NetworkType.Basic) {
super.release(nic, vm, reservationId);
if (logger.isDebugEnabled()) {
logger.debug("Released nic: " + nic);
logger.debug(String.format("Released nic: %s for vm %s", nic, vm));
}
return true;
} else {
nic.deallocate();
if (logger.isDebugEnabled()) {
logger.debug("Released nic: " + nic);
logger.debug(String.format("Released nic: %s for vm %s", nic, vm));
}
return true;
}
@ -190,7 +197,7 @@ public class ControlNetworkGuru extends PodBasedNetworkGuru implements NetworkGu
nic.deallocate();
if (logger.isDebugEnabled()) {
logger.debug("Released nic: " + nic);
logger.debug(String.format("Released nic: %s for vm %s", nic, vm));
}
return true;

View File

@ -162,7 +162,7 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru {
nic.deallocate();
if (logger.isDebugEnabled()) {
logger.debug("Released nic: " + nic);
logger.debug(String.format("Released nic: %s for vm %s", nic, vm));
}
return true;

Some files were not shown because too many files have changed in this diff Show More