mirror of https://github.com/apache/cloudstack.git
[20.3] Address limit checks for VM, CPU, memory, volume, and primary storage
This commit is contained in:
parent
360b64ce1e
commit
0a4b4c6af0
|
|
@ -82,7 +82,7 @@ public interface ProjectService {
|
|||
|
||||
Project updateProject(long id, String name, String displayText, String newOwnerName, Long userId, Role newRole) throws ResourceAllocationException;
|
||||
|
||||
boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType);
|
||||
boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType) throws ResourceAllocationException;
|
||||
|
||||
boolean deleteAccountFromProject(long projectId, String accountName);
|
||||
|
||||
|
|
@ -100,6 +100,6 @@ public interface ProjectService {
|
|||
|
||||
Project findByProjectAccountIdIncludingRemoved(long projectAccountId);
|
||||
|
||||
boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole);
|
||||
boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole) throws ResourceAllocationException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import com.cloud.exception.ResourceAllocationException;
|
|||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
|
||||
public interface ResourceLimitService {
|
||||
|
||||
|
|
@ -246,12 +247,12 @@ public interface ResourceLimitService {
|
|||
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 checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
List<String> getResourceLimitStorageTagsForResourceCountOperation(Boolean display, DiskOffering diskOffering);
|
||||
void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize,
|
||||
DiskOffering currentOffering, DiskOffering newOffering) throws ResourceAllocationException;
|
||||
DiskOffering currentOffering, DiskOffering newOffering, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
|
||||
void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException;
|
||||
void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
|
||||
void incrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
|
||||
void decrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
|
||||
|
|
@ -268,20 +269,18 @@ public interface ResourceLimitService {
|
|||
|
||||
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 checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
void incrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
|
||||
void decrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
|
||||
|
||||
void checkVmResourceLimitsForServiceOfferingChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
|
||||
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template) throws ResourceAllocationException;
|
||||
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
|
||||
void checkVmResourceLimitsForTemplateChange(Account owner, Boolean display, ServiceOffering offering,
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate) throws ResourceAllocationException;
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate, List<Reserver> reservations) throws ResourceAllocationException;
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.user.account;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import org.apache.cloudstack.api.ApiArgValidator;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
|
|
@ -106,7 +107,7 @@ public class AddAccountToProjectCmd extends BaseAsyncCmd {
|
|||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public void execute() throws ResourceAllocationException {
|
||||
if (accountName == null && email == null) {
|
||||
throw new InvalidParameterValueException("Either accountName or email is required");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.apache.cloudstack.api.command.user.account;
|
||||
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiArgValidator;
|
||||
|
|
@ -111,7 +112,7 @@ public class AddUserToProjectCmd extends BaseAsyncCmd {
|
|||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public void execute() throws ResourceAllocationException {
|
||||
validateInput();
|
||||
boolean result = _projectService.addUserToProject(getProjectId(), getUsername(), getEmail(), getProjectRoleId(), getRoleType());
|
||||
if (result) {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,14 @@
|
|||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com.cloud.resourcelimit;
|
||||
package org.apache.cloudstack.resourcelimit;
|
||||
|
||||
/**
|
||||
* Interface implemented by <code>CheckedReservation</code>.
|
||||
* </br></br>
|
||||
* This is defined in <code>cloud-api</code> to allow methods declared in modules that do not depend on <code>cloud-server</code>
|
||||
* to receive <code>CheckedReservations</code> as parameters.
|
||||
*/
|
||||
public interface Reserver extends AutoCloseable {
|
||||
|
||||
void close();
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.test;
|
||||
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
|
@ -149,6 +150,8 @@ public class AddAccountToProjectCmdTest extends TestCase {
|
|||
addAccountToProjectCmd.execute();
|
||||
} catch (InvalidParameterValueException exception) {
|
||||
Assert.assertEquals("Either accountName or email is required", exception.getLocalizedMessage());
|
||||
} catch (ResourceAllocationException exception) {
|
||||
Assert.fail();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4757,9 +4757,20 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
|
||||
private void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering) {
|
||||
Map<String, String> details = userVmDetailsDao.listDetailsKeyPairs(vmId);
|
||||
details.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
|
||||
details.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
|
||||
details.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
|
||||
|
||||
// We need to restore only the customizable parameters. If we save a parameter that is not customizable and attempt
|
||||
// to restore a VM snapshot, com.cloud.vm.UserVmManagerImpl.validateCustomParameters will fail.
|
||||
ServiceOffering unfilledOffering = _serviceOfferingDao.findByIdIncludingRemoved(serviceOffering.getId());
|
||||
if (unfilledOffering.getCpu() == null) {
|
||||
details.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
|
||||
}
|
||||
if (unfilledOffering.getSpeed() == null) {
|
||||
details.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
|
||||
}
|
||||
if (unfilledOffering.getRamSize() == null) {
|
||||
details.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
|
||||
}
|
||||
|
||||
List<UserVmDetailVO> detailList = new ArrayList<>();
|
||||
for (Map.Entry<String, String> entry: details.entrySet()) {
|
||||
UserVmDetailVO detailVO = new UserVmDetailVO(vmId, entry.getKey(), entry.getValue(), true);
|
||||
|
|
|
|||
|
|
@ -3097,9 +3097,6 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
CallContext.current().setEventDetails("Network Id: " + network.getId());
|
||||
CallContext.current().putContextParameter(Network.class, network.getUuid());
|
||||
return network;
|
||||
} catch (Exception e) {
|
||||
logger.error(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import javax.inject.Inject;
|
|||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.resourcelimit.ReservationHelper;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
|
|
@ -77,6 +78,7 @@ import org.apache.cloudstack.framework.jobs.AsyncJobManager;
|
|||
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
|
||||
import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.secret.PassphraseVO;
|
||||
import org.apache.cloudstack.secret.dao.PassphraseDao;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
|
|
@ -1867,14 +1869,20 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||
template == null ? null : template.getSize(),
|
||||
vol.getPassphraseId() != null);
|
||||
|
||||
if (newSize != vol.getSize()) {
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findByIdIncludingRemoved(vol.getDiskOfferingId());
|
||||
if (newSize == vol.getSize()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findByIdIncludingRemoved(vol.getDiskOfferingId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
VMInstanceVO vm = vol.getInstanceId() != null ? vmInstanceDao.findById(vol.getInstanceId()) : null;
|
||||
if (vm == null || vm.getType() == VirtualMachine.Type.User) {
|
||||
// Update resource count for user vm volumes when volume is attached
|
||||
if (newSize > vol.getSize()) {
|
||||
_resourceLimitMgr.checkPrimaryStorageResourceLimit(_accountMgr.getActiveAccountById(vol.getAccountId()),
|
||||
vol.isDisplay(), newSize - vol.getSize(), diskOffering);
|
||||
vol.isDisplay(), newSize - vol.getSize(), diskOffering, reservations);
|
||||
_resourceLimitMgr.incrementVolumePrimaryStorageResourceCount(vol.getAccountId(), vol.isDisplay(),
|
||||
newSize - vol.getSize(), diskOffering);
|
||||
} else {
|
||||
|
|
@ -1882,9 +1890,11 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||
vol.getSize() - newSize, diskOffering);
|
||||
}
|
||||
}
|
||||
vol.setSize(newSize);
|
||||
_volsDao.persist(vol);
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
vol.setSize(newSize);
|
||||
_volsDao.persist(vol);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -544,7 +544,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_USER_ADD, eventDescription = "adding user to project", async = true)
|
||||
public boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole) {
|
||||
public boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole) throws ResourceAllocationException {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
Project project = getProject(projectId);
|
||||
|
|
@ -614,8 +614,6 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
logger.warn("Failed to add user to project: {}", project);
|
||||
return false;
|
||||
}
|
||||
} catch (ResourceAllocationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -814,7 +812,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ACCOUNT_ADD, eventDescription = "adding account to project", async = true)
|
||||
public boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType) {
|
||||
public boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType) throws ResourceAllocationException {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
//check that the project exists
|
||||
|
|
@ -892,8 +890,6 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C
|
|||
logger.warn("Failed to add account {} to project {}", accountName, project);
|
||||
return false;
|
||||
}
|
||||
} catch (ResourceAllocationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,13 +20,16 @@ package com.cloud.resourcelimit;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.reservation.ReservationVO;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.user.ResourceReservation;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
|
@ -48,12 +51,15 @@ public class CheckedReservation implements Reserver {
|
|||
ReservationDao reservationDao;
|
||||
|
||||
ResourceLimitService resourceLimitService;
|
||||
private final Account account;
|
||||
private Account account;
|
||||
private Long domainId;
|
||||
private final ResourceType resourceType;
|
||||
private Long amount;
|
||||
private ResourceType resourceType;
|
||||
private Long resourceId;
|
||||
private Long reservationAmount;
|
||||
private List<String> reservationTags;
|
||||
private Long existingAmount;
|
||||
private List<String> existingLimitTags;
|
||||
private List<ResourceReservation> reservations;
|
||||
private List<String> resourceLimitTags;
|
||||
|
||||
private String getContextParameterKey() {
|
||||
return getResourceReservationContextParameterKey(resourceType);
|
||||
|
|
@ -100,9 +106,25 @@ public class CheckedReservation implements Reserver {
|
|||
this.reservations.add(reservation);
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, ResourceType resourceType, List<String> resourceLimitTags, Long amount,
|
||||
ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, resourceType, null, resourceLimitTags, amount, reservationDao, resourceLimitService);
|
||||
// TODO: refactor these into a Builder to avoid having so many constructors
|
||||
public CheckedReservation(Account account, ResourceType resourceType, List<String> resourceLimitTags, Long reservationAmount,
|
||||
ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, resourceType, null, resourceLimitTags, null, reservationAmount, null, reservationDao, resourceLimitService);
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, ResourceType resourceType, Long resourceId, List<String> reservedTags,
|
||||
List<String> existingTags, Long reservationAmount, Long existingAmount, ReservationDao reservationDao,
|
||||
ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, null, resourceType, resourceId, reservedTags, existingTags, reservationAmount, existingAmount, reservationDao, resourceLimitService);
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, Long domainId, ResourceType resourceType, Long resourceId, List<String> reservedTags,
|
||||
Long reservationAmount, ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, domainId, resourceType, resourceId, reservedTags, null, reservationAmount, null, reservationDao, resourceLimitService);
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, ResourceType resourceType, Long resourceId, List<String> reservedTags, Long reservationAmount, ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, null, resourceType, resourceId, reservedTags, null, reservationAmount, null, reservationDao, resourceLimitService);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -110,36 +132,43 @@ public class CheckedReservation implements Reserver {
|
|||
* - create DB entry for reservation
|
||||
* - hold the id of this record as a ticket for implementation
|
||||
*
|
||||
* @param amount positive number of the resource type to reserve
|
||||
* @param reservationAmount positive number of the resource type to reserve
|
||||
* @throws ResourceAllocationException
|
||||
*/
|
||||
public CheckedReservation(Account account, ResourceType resourceType, Long resourceId, List<String> resourceLimitTags, Long amount,
|
||||
ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, account.getDomainId(), resourceType, resourceId, resourceLimitTags, amount, reservationDao, resourceLimitService);
|
||||
}
|
||||
public CheckedReservation(Account account, Long domainId, ResourceType resourceType, Long resourceId, List<String> reservedTags,
|
||||
List<String> existingTags, Long reservationAmount, Long existingAmount, ReservationDao reservationDao,
|
||||
ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
|
||||
if (ObjectUtils.allNull(account, domainId)) {
|
||||
logger.debug("Not reserving any {} resources, as no account/domain was provided.", resourceType);
|
||||
return;
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, Long domainId, ResourceType resourceType, Long resourceId, List<String> resourceLimitTags, Long amount,
|
||||
ReservationDao reservationDao, ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this.reservationDao = reservationDao;
|
||||
this.resourceLimitService = resourceLimitService;
|
||||
this.account = account;
|
||||
|
||||
this.domainId = domainId;
|
||||
if (domainId == null) {
|
||||
this.domainId = account.getDomainId();
|
||||
domainId = account.getDomainId();
|
||||
}
|
||||
this.domainId = domainId;
|
||||
|
||||
this.resourceType = resourceType;
|
||||
this.amount = amount;
|
||||
this.reservationAmount = reservationAmount;
|
||||
this.existingAmount = existingAmount;
|
||||
this.reservations = new ArrayList<>();
|
||||
this.resourceLimitTags = resourceLimitTags;
|
||||
|
||||
if (this.amount != null && this.amount != 0) {
|
||||
if (amount > 0) {
|
||||
this.reservationTags = getTagsWithoutNull(reservedTags);
|
||||
this.existingLimitTags = getTagsWithoutNull(existingTags);
|
||||
|
||||
// TODO: refactor me
|
||||
if (this.reservationAmount != null && this.reservationAmount != 0) {
|
||||
if (reservationAmount > 0) {
|
||||
setGlobalLock();
|
||||
if (quotaLimitLock.lock(TRY_TO_GET_LOCK_TIME)) {
|
||||
try {
|
||||
checkLimitAndPersistReservations(account, this.domainId, resourceType, resourceId, resourceLimitTags, amount);
|
||||
adjustCountToNotConsiderExistingAmount();
|
||||
checkLimitAndPersistReservations(account, this.domainId, resourceType, resourceId, reservationTags, reservationAmount);
|
||||
CallContext.current().putContextParameter(getContextParameterKey(), getIds());
|
||||
} catch (NullPointerException npe) {
|
||||
throw new CloudRuntimeException("not enough means to check limits", npe);
|
||||
|
|
@ -150,7 +179,7 @@ public class CheckedReservation implements Reserver {
|
|||
throw new ResourceAllocationException(String.format("unable to acquire resource reservation \"%s\"", quotaLimitLock.getName()), resourceType);
|
||||
}
|
||||
} else {
|
||||
checkLimitAndPersistReservations(account, this.domainId, resourceType, resourceId, resourceLimitTags, amount);
|
||||
checkLimitAndPersistReservations(account, this.domainId, resourceType, resourceId, reservationTags, reservationAmount);
|
||||
}
|
||||
} else {
|
||||
logger.debug("not reserving any amount of resources for {} in domain {}, type: {}, tag: {}",
|
||||
|
|
@ -158,6 +187,20 @@ public class CheckedReservation implements Reserver {
|
|||
}
|
||||
}
|
||||
|
||||
protected List<String> getTagsWithoutNull(List<String> tags) {
|
||||
if (tags == null) {
|
||||
return null;
|
||||
}
|
||||
return tags.stream().filter(Objects::nonNull).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
protected void adjustCountToNotConsiderExistingAmount() throws ResourceAllocationException {
|
||||
if (existingAmount == null || existingAmount == 0) {
|
||||
return;
|
||||
}
|
||||
checkLimitAndPersistReservations(account, domainId, resourceType, resourceId, existingLimitTags, -1 * existingAmount);
|
||||
}
|
||||
|
||||
public CheckedReservation(Account account, ResourceType resourceType, Long amount, ReservationDao reservationDao,
|
||||
ResourceLimitService resourceLimitService) throws ResourceAllocationException {
|
||||
this(account, resourceType, null, amount, reservationDao, resourceLimitService);
|
||||
|
|
@ -183,11 +226,11 @@ public class CheckedReservation implements Reserver {
|
|||
}
|
||||
|
||||
public String getResourceLimitTagsAsString() {
|
||||
return CollectionUtils.isNotEmpty(resourceLimitTags) ? StringUtils.join(resourceLimitTags) : null;
|
||||
return CollectionUtils.isNotEmpty(reservationTags) ? StringUtils.join(reservationTags) : null;
|
||||
}
|
||||
|
||||
public Long getReservedAmount() {
|
||||
return amount;
|
||||
return reservationAmount;
|
||||
}
|
||||
|
||||
public List<ResourceReservation> getReservations() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// 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.resourcelimit;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ReservationHelper {
|
||||
|
||||
public static void closeAll(List<Reserver> reservations) throws CloudRuntimeException {
|
||||
for (Reserver reservation : reservations) {
|
||||
reservation.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -52,6 +52,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
|||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.reservation.ReservationVO;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
||||
|
|
@ -168,6 +169,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
@Inject
|
||||
private ReservationDao reservationDao;
|
||||
@Inject
|
||||
private ResourceLimitService resourceLimitService;
|
||||
@Inject
|
||||
protected SnapshotDao _snapshotDao;
|
||||
@Inject
|
||||
private SnapshotDataStoreDao _snapshotDataStoreDao;
|
||||
|
|
@ -1662,54 +1665,53 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException {
|
||||
public void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitStorageTagsForResourceCountOperation(display, diskOffering);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.volume, tag);
|
||||
if (size != null) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.primary_storage, tag, size);
|
||||
}
|
||||
|
||||
CheckedReservation volumeReservation = new CheckedReservation(owner, ResourceType.volume, tags, 1L, reservationDao, resourceLimitService);
|
||||
reservations.add(volumeReservation);
|
||||
|
||||
if (size != null) {
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(owner, ResourceType.primary_storage, tags, size, reservationDao, resourceLimitService);
|
||||
reservations.add(primaryStorageReservation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException {
|
||||
public void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitStorageTagsForResourceCountOperation(display, diskOffering);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
if (size != null) {
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.primary_storage, tag, size);
|
||||
}
|
||||
}
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(owner, ResourceType.primary_storage, tags, size, reservationDao, resourceLimitService);
|
||||
reservations.add(primaryStorageReservation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize,
|
||||
DiskOffering currentOffering, DiskOffering newOffering
|
||||
DiskOffering currentOffering, DiskOffering newOffering, List<Reserver> reservations
|
||||
) throws ResourceAllocationException {
|
||||
Ternary<Set<String>, Set<String>, Set<String>> updatedResourceLimitStorageTags = getResourceLimitStorageTagsForDiskOfferingChange(display, currentOffering, newOffering);
|
||||
if (updatedResourceLimitStorageTags == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> sameTags = updatedResourceLimitStorageTags.first();
|
||||
Set<String> newTags = updatedResourceLimitStorageTags.second();
|
||||
|
||||
if (newSize > currentSize) {
|
||||
for (String tag : sameTags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.primary_storage, tag, newSize - currentSize);
|
||||
}
|
||||
List<String> currentTags = getResourceLimitStorageTagsForResourceCountOperation(true, currentOffering);
|
||||
List<String> tagsAfterUpdate = getResourceLimitStorageTagsForResourceCountOperation(true, newOffering);
|
||||
if (currentTags.isEmpty() && tagsAfterUpdate.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String tag : newTags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.volume, tag, 1L);
|
||||
checkResourceLimitWithTag(owner, ResourceType.primary_storage, tag, newSize);
|
||||
}
|
||||
CheckedReservation volumeReservation = new CheckedReservation(owner, ResourceType.volume, null, tagsAfterUpdate,
|
||||
currentTags, 1L, 1L, reservationDao, resourceLimitService);
|
||||
reservations.add(volumeReservation);
|
||||
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(owner, ResourceType.primary_storage, null,
|
||||
tagsAfterUpdate, currentTags, newSize, currentSize, reservationDao, resourceLimitService);
|
||||
reservations.add(primaryStorageReservation);
|
||||
}
|
||||
|
||||
@DB
|
||||
|
|
@ -1932,18 +1934,23 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template) throws ResourceAllocationException {
|
||||
public void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitHostTagsForResourceCountOperation(display, serviceOffering, template);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CheckedReservation vmReservation = new CheckedReservation(owner, ResourceType.user_vm, tags, 1L, reservationDao, resourceLimitService);
|
||||
reservations.add(vmReservation);
|
||||
|
||||
Long cpu = serviceOffering.getCpu() != null ? Long.valueOf(serviceOffering.getCpu()) : 0L;
|
||||
CheckedReservation cpuReservation = new CheckedReservation(owner, ResourceType.cpu, tags, cpu, reservationDao, resourceLimitService);
|
||||
reservations.add(cpuReservation);
|
||||
|
||||
Long ram = serviceOffering.getRamSize() != null ? Long.valueOf(serviceOffering.getRamSize()) : 0L;
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.user_vm, tag);
|
||||
checkResourceLimitWithTag(owner, ResourceType.cpu, tag, cpu);
|
||||
checkResourceLimitWithTag(owner, ResourceType.memory, tag, ram);
|
||||
}
|
||||
CheckedReservation memReservation = new CheckedReservation(owner, ResourceType.memory, tags, ram, reservationDao, resourceLimitService);
|
||||
reservations.add(memReservation);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1989,76 +1996,53 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
|
||||
@Override
|
||||
public void checkVmResourceLimitsForTemplateChange(Account owner, Boolean display, ServiceOffering offering,
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate) throws ResourceAllocationException {
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
checkVmResourceLimitsForServiceOfferingAndTemplateChange(owner, display, null, null,
|
||||
null, null, offering, offering, currentTemplate, newTemplate);
|
||||
null, null, offering, offering, currentTemplate, newTemplate, reservations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmResourceLimitsForServiceOfferingChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
|
||||
Long currentMemory, Long newMemory,
|
||||
ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template
|
||||
ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template, List<Reserver> reservations
|
||||
) throws ResourceAllocationException {
|
||||
checkVmResourceLimitsForServiceOfferingAndTemplateChange(owner, display, currentCpu, newCpu, currentMemory, newMemory, currentOffering,
|
||||
newOffering != null ? newOffering : currentOffering, template, template);
|
||||
newOffering != null ? newOffering : currentOffering, template, template, reservations);
|
||||
}
|
||||
|
||||
private void checkVmResourceLimitsForServiceOfferingAndTemplateChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
|
||||
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering,
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate
|
||||
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate, List<Reserver> reservations
|
||||
) throws ResourceAllocationException {
|
||||
Ternary<Set<String>, Set<String>, Set<String>> updatedResourceLimitHostTags = getResourceLimitHostTagsForVmServiceOfferingAndTemplateChange(display, currentOffering, newOffering, currentTemplate, newTemplate);
|
||||
if (updatedResourceLimitHostTags == null) {
|
||||
List<String> currentTags = getResourceLimitHostTagsForResourceCountOperation(true, currentOffering, currentTemplate);
|
||||
List<String> tagsAfterUpdate = getResourceLimitHostTagsForResourceCountOperation(true, newOffering, newTemplate);
|
||||
if (currentTags.isEmpty() && tagsAfterUpdate.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CheckedReservation vmReservation = new CheckedReservation(owner, ResourceType.user_vm, null, tagsAfterUpdate,
|
||||
currentTags, 1L, 1L, reservationDao, resourceLimitService);
|
||||
reservations.add(vmReservation);
|
||||
|
||||
if (currentCpu == null) {
|
||||
currentCpu = currentOffering.getCpu() != null ? Long.valueOf(currentOffering.getCpu()) : 0L;
|
||||
}
|
||||
if (newCpu == null) {
|
||||
newCpu = newOffering.getCpu() != null ? Long.valueOf(newOffering.getCpu()) : 0L;
|
||||
}
|
||||
CheckedReservation cpuReservation = new CheckedReservation(owner, ResourceType.cpu, null, tagsAfterUpdate,
|
||||
currentTags, newCpu, currentCpu, reservationDao, resourceLimitService);
|
||||
reservations.add(cpuReservation);
|
||||
|
||||
if (currentMemory == null) {
|
||||
currentMemory = currentOffering.getRamSize() != null ? Long.valueOf(currentOffering.getRamSize()) : 0L;
|
||||
}
|
||||
if (newMemory == null) {
|
||||
newMemory = newOffering.getRamSize() != null ? Long.valueOf(newOffering.getRamSize()) : 0L;
|
||||
}
|
||||
|
||||
Set<String> sameTags = updatedResourceLimitHostTags.first();
|
||||
Set<String> newTags = updatedResourceLimitHostTags.second();
|
||||
|
||||
if (newCpu - currentCpu > 0 || newMemory - currentMemory > 0) {
|
||||
for (String tag : sameTags) {
|
||||
if (newCpu - currentCpu > 0) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.cpu, tag, newCpu - currentCpu);
|
||||
}
|
||||
|
||||
if (newMemory - currentMemory > 0) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.memory, tag, newMemory - currentMemory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String tag : newTags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.user_vm, tag, 1L);
|
||||
checkResourceLimitWithTag(owner, ResourceType.cpu, tag, newCpu);
|
||||
checkResourceLimitWithTag(owner, ResourceType.memory, tag, newMemory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmCpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitHostTagsForResourceCountOperation(display, serviceOffering, template);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
if (cpu == null) {
|
||||
cpu = serviceOffering.getCpu() != null ? Long.valueOf(serviceOffering.getCpu()) : 0L;
|
||||
}
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.cpu, tag, cpu);
|
||||
}
|
||||
CheckedReservation memReservation = new CheckedReservation(owner, ResourceType.memory, null, tagsAfterUpdate,
|
||||
currentTags, newMemory, currentMemory, reservationDao, resourceLimitService);
|
||||
reservations.add(memReservation);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2089,20 +2073,6 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmMemoryResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) throws ResourceAllocationException {
|
||||
List<String> tags = getResourceLimitHostTagsForResourceCountOperation(display, serviceOffering, template);
|
||||
if (CollectionUtils.isEmpty(tags)) {
|
||||
return;
|
||||
}
|
||||
if (memory == null) {
|
||||
memory = serviceOffering.getRamSize() != null ? Long.valueOf(serviceOffering.getRamSize()) : 0L;
|
||||
}
|
||||
for (String tag : tags) {
|
||||
checkResourceLimitWithTag(owner, ResourceType.memory, tag, memory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) {
|
||||
List<String> tags = getResourceLimitHostTagsForResourceCountOperation(display, serviceOffering, template);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import java.util.stream.Collectors;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.resourcelimit.ReservationHelper;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
|
@ -93,6 +94,7 @@ import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO;
|
|||
import org.apache.cloudstack.resourcedetail.SnapshotPolicyDetailVO;
|
||||
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
|
||||
import org.apache.cloudstack.resourcedetail.dao.SnapshotPolicyDetailsDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
import org.apache.cloudstack.storage.command.AttachAnswer;
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
|
|
@ -425,9 +427,17 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
Long diskOfferingId = cmd.getDiskOfferingId();
|
||||
String imageStoreUuid = cmd.getImageStoreUuid();
|
||||
|
||||
validateVolume(caller, ownerId, zoneId, volumeName, url, format, diskOfferingId);
|
||||
VolumeVO volume;
|
||||
|
||||
VolumeVO volume = persistVolume(owner, zoneId, volumeName, url, format, diskOfferingId, Volume.State.Allocated);
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
|
||||
validateVolume(caller, ownerId, zoneId, volumeName, url, format, diskOfferingId, reservations);
|
||||
volume = persistVolume(owner, zoneId, volumeName, url, format, diskOfferingId, Volume.State.Allocated);
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
|
||||
VolumeInfo vol = volFactory.getVolume(volume.getId());
|
||||
|
||||
|
|
@ -467,7 +477,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
final Long diskOfferingId = cmd.getDiskOfferingId();
|
||||
String imageStoreUuid = cmd.getImageStoreUuid();
|
||||
|
||||
validateVolume(caller, ownerId, zoneId, volumeName, null, format, diskOfferingId);
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
validateVolume(caller, ownerId, zoneId, volumeName, null, format, diskOfferingId, reservations);
|
||||
|
||||
return Transaction.execute(new TransactionCallbackWithException<GetUploadParamsResponse, MalformedURLException>() {
|
||||
@Override
|
||||
|
|
@ -535,9 +547,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
return response;
|
||||
}
|
||||
});
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format, Long diskOfferingId) throws ResourceAllocationException {
|
||||
private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format, Long diskOfferingId, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
// permission check
|
||||
Account volumeOwner = _accountMgr.getActiveAccountById(ownerId);
|
||||
|
|
@ -548,7 +564,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
_accountMgr.checkAccess(caller, null, true, volumeOwner);
|
||||
|
||||
// Check that the resource limit for volumes won't be exceeded
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(volumeOwner, true, null, diskOffering);
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(volumeOwner, true, null, diskOffering, reservations);
|
||||
|
||||
// Verify that zone exists
|
||||
DataCenterVO zone = _dcDao.findById(zoneId);
|
||||
|
|
@ -926,8 +942,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
if (tags.size() == 1 && tags.get(0) == null) {
|
||||
tags = new ArrayList<>();
|
||||
}
|
||||
try (CheckedReservation volumeReservation = new CheckedReservation(owner, ResourceType.volume, null, tags, 1L, reservationDao, _resourceLimitMgr);
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(owner, ResourceType.primary_storage, null, tags, size, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(owner, displayVolume, size, diskOffering, reservations);
|
||||
|
||||
// Verify that zone exists
|
||||
DataCenterVO zone = _dcDao.findById(zoneId);
|
||||
|
|
@ -950,9 +968,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
|
||||
return commitVolume(cmd, caller, owner, displayVolume, zoneId, diskOfferingId, provisioningType, size, minIops, maxIops, parentVolume, userSpecifiedName,
|
||||
_uuidMgr.generateUuid(Volume.class, cmd.getCustomId()), details);
|
||||
} catch (Exception e) {
|
||||
logger.error(e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1278,7 +1295,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
if (dataStore != null && dataStore.getDriver() instanceof PrimaryDataStoreDriver) {
|
||||
newSize = ((PrimaryDataStoreDriver) dataStore.getDriver()).getVolumeSizeRequiredOnPool(newSize, null, isEncryptionRequired);
|
||||
}
|
||||
validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, diskOffering, newDiskOffering);
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, diskOffering, newDiskOffering, reservations);
|
||||
|
||||
// Note: The storage plug-in in question should perform validation on the IOPS to check if a sufficient number of IOPS is available to perform
|
||||
// the requested change
|
||||
|
|
@ -1406,6 +1426,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
|
||||
return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null,
|
||||
shrinkOk);
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1839,12 +1863,11 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
throw new InvalidParameterValueException("Please specify a volume in Destroy state.");
|
||||
}
|
||||
|
||||
DiskOffering diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize());
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("primary storage resource limit check failed", e);
|
||||
throw new InvalidParameterValueException(e.getMessage());
|
||||
}
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(_accountMgr.getAccount(volume.getAccountId()), volume.isDisplayVolume(), volume.getSize(), diskOffering, reservations);
|
||||
|
||||
try {
|
||||
_volsDao.detachVolume(volume.getId());
|
||||
|
|
@ -1856,6 +1879,12 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
_resourceLimitMgr.incrementVolumeResourceCount(volume.getAccountId(), volume.isDisplay(),
|
||||
volume.getSize(), _diskOfferingDao.findById(volume.getDiskOfferingId()));
|
||||
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("primary storage resource limit check failed", e);
|
||||
throw new InvalidParameterValueException(e.getMessage());
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
|
||||
publishVolumeCreationUsageEvent(volume);
|
||||
|
||||
|
|
@ -2085,7 +2114,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
newSize = ((PrimaryDataStoreDriver) dataStore.getDriver()).getVolumeSizeRequiredOnPool(newSize, null, newDiskOffering.getEncrypt());
|
||||
}
|
||||
|
||||
validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, existingDiskOffering, newDiskOffering);
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, existingDiskOffering, newDiskOffering, reservations);
|
||||
|
||||
/* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
|
||||
// We need to publish this event to usage_volume table
|
||||
|
|
@ -2175,6 +2206,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
}
|
||||
|
||||
return volume;
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStorageWithTheNewDiskOffering(VolumeVO volume, DiskOfferingVO newDiskOffering) {
|
||||
|
|
@ -2380,7 +2415,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
}
|
||||
|
||||
private void validateVolumeResizeWithSize(VolumeVO volume, long currentSize, Long newSize, boolean shrinkOk,
|
||||
DiskOfferingVO existingDiskOffering, DiskOfferingVO newDiskOffering) throws ResourceAllocationException {
|
||||
DiskOfferingVO existingDiskOffering, DiskOfferingVO newDiskOffering, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
// if the caller is looking to change the size of the volume
|
||||
if (newSize != null && currentSize != newSize) {
|
||||
|
|
@ -2450,7 +2485,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
/* Check resource limit for this account */
|
||||
_resourceLimitMgr.checkVolumeResourceLimitForDiskOfferingChange(_accountMgr.getAccount(volume.getAccountId()),
|
||||
volume.isDisplayVolume(), currentSize, newSize != null ? newSize : currentSize,
|
||||
existingDiskOffering, newDiskOffering);
|
||||
existingDiskOffering, newDiskOffering, reservations);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2622,7 +2657,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
|
||||
checkForBackups(vm, true);
|
||||
|
||||
checkRightsToAttach(caller, volumeToAttach, vm);
|
||||
_accountMgr.checkAccess(caller, null, true, volumeToAttach, vm);
|
||||
|
||||
HypervisorType rootDiskHyperType = vm.getHypervisorType();
|
||||
HypervisorType volumeToAttachHyperType = _volsDao.getHypervisorType(volumeToAttach.getId());
|
||||
|
|
@ -2649,6 +2684,12 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
throw new InvalidParameterValueException("Volume's disk offering has encryption enabled, but volume encryption is not supported for hypervisor type " + rootDiskHyperType);
|
||||
}
|
||||
|
||||
Account owner = _accountDao.findById(volumeToAttach.getAccountId());
|
||||
List<String> resourceLimitStorageTags = _resourceLimitMgr.getResourceLimitStorageTagsForResourceCountOperation(true, diskOffering);
|
||||
Long requiredPrimaryStorageSpace = getRequiredPrimaryStorageSizeForVolumeAttach(resourceLimitStorageTags, volumeToAttach);
|
||||
|
||||
try (CheckedReservation primaryStorageReservation = new CheckedReservation(owner, ResourceType.primary_storage, resourceLimitStorageTags, requiredPrimaryStorageSpace, reservationDao, _resourceLimitMgr)) {
|
||||
|
||||
_jobMgr.updateAsyncJobAttachment(job.getId(), "Volume", volumeId);
|
||||
|
||||
if (asyncExecutionContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
|
||||
|
|
@ -2656,9 +2697,21 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
} else {
|
||||
return getVolumeAttachJobResult(vmId, volumeId, deviceId);
|
||||
}
|
||||
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("primary storage resource limit check failed", e);
|
||||
throw new InvalidParameterValueException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable private Volume getVolumeAttachJobResult(Long vmId, Long volumeId, Long deviceId) {
|
||||
protected Long getRequiredPrimaryStorageSizeForVolumeAttach(List<String> resourceLimitStorageTags, VolumeInfo volumeToAttach) {
|
||||
if (CollectionUtils.isEmpty(resourceLimitStorageTags) || Arrays.asList(Volume.State.Allocated, Volume.State.Ready).contains(volumeToAttach.getState())) {
|
||||
return 0L;
|
||||
}
|
||||
return volumeToAttach.getSize();
|
||||
}
|
||||
|
||||
@Nullable protected Volume getVolumeAttachJobResult(Long vmId, Long volumeId, Long deviceId) {
|
||||
Outcome<Volume> outcome = attachVolumeToVmThroughJobQueue(vmId, volumeId, deviceId);
|
||||
|
||||
Volume vol = null;
|
||||
|
|
@ -2707,21 +2760,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
}
|
||||
}
|
||||
|
||||
private void checkRightsToAttach(Account caller, VolumeInfo volumeToAttach, UserVmVO vm) {
|
||||
_accountMgr.checkAccess(caller, null, true, volumeToAttach, vm);
|
||||
|
||||
Account owner = _accountDao.findById(volumeToAttach.getAccountId());
|
||||
|
||||
if (!Arrays.asList(Volume.State.Allocated, Volume.State.Ready).contains(volumeToAttach.getState())) {
|
||||
try {
|
||||
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, volumeToAttach.getSize());
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("primary storage resource limit check failed", e);
|
||||
throw new InvalidParameterValueException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForVMSnapshots(Long vmId, UserVmVO vm) {
|
||||
// if target VM has associated VM snapshots
|
||||
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
|
||||
|
|
@ -4207,7 +4245,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
_accountMgr.checkAccess(caller, null, true, oldAccount);
|
||||
_accountMgr.checkAccess(caller, null, true, newAccount);
|
||||
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(newAccount, true, volume.getSize(), _diskOfferingDao.findById(volume.getDiskOfferingId()));
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
_resourceLimitMgr.checkVolumeResourceLimit(newAccount, true, volume.getSize(), _diskOfferingDao.findById(volume.getDiskOfferingId()), reservations);
|
||||
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
|
|
@ -4217,6 +4257,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
});
|
||||
|
||||
return volume;
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateVolumeAccount(Account oldAccount, VolumeVO volume, Account newAccount) {
|
||||
|
|
|
|||
|
|
@ -1759,16 +1759,13 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.snapshot);
|
||||
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), storeResourceType, volume.getSize());
|
||||
return snapshot;
|
||||
} catch (Exception e) {
|
||||
if (e instanceof ResourceAllocationException) {
|
||||
if (snapshotType != Type.MANUAL) {
|
||||
String msg = String.format("Snapshot resource limit exceeded for account id : %s. Failed to create recurring snapshots", owner.getId());
|
||||
logger.warn(msg);
|
||||
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, msg + ". Please, use updateResourceLimit to increase the limit");
|
||||
}
|
||||
throw (ResourceAllocationException) e;
|
||||
} catch (ResourceAllocationException e) {
|
||||
if (snapshotType != Type.MANUAL) {
|
||||
String msg = String.format("Snapshot resource limit exceeded for account id : %s. Failed to create recurring snapshots", owner.getId());
|
||||
logger.warn(msg);
|
||||
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, msg + ". Please, use updateResourceLimit to increase the limit");
|
||||
}
|
||||
throw new CloudRuntimeException(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -357,6 +357,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
|
||||
// Secondary storage resource count is not incremented for BareMetalTemplateAdapter
|
||||
// Note: checking the file size before registering will require the Management Server host to have access to the Internet and a DNS server
|
||||
// If it does not, UriUtils.getRemoteSize will return 0L.
|
||||
long secondaryStorageUsage = adapter instanceof HypervisorTemplateAdapter && !cmd.isDirectDownload() ?
|
||||
UriUtils.getRemoteSize(cmd.getUrl(), StorageManager.DataStoreDownloadFollowRedirects.value()) : 0L;
|
||||
|
||||
|
|
@ -365,7 +366,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
TemplateProfile profile = adapter.prepare(cmd);
|
||||
VMTemplateVO template = adapter.create(profile);
|
||||
|
||||
// Secondary storage resource usage will be recalculated in com.cloud.template.HypervisorTemplateAdapter.createTemplateAsyncCallBack
|
||||
// Secondary storage resource usage will be incremented in com.cloud.template.HypervisorTemplateAdapter.createTemplateAsyncCallBack
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
|
||||
if (secondaryStorageUsage > 0) {
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.secondary_storage, secondaryStorageUsage);
|
||||
|
|
@ -405,7 +406,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
TemplateProfile profile = adapter.prepare(cmd);
|
||||
VMTemplateVO template = adapter.create(profile);
|
||||
|
||||
// Secondary storage resource usage will be recalculated in com.cloud.template.HypervisorTemplateAdapter.createTemplateAsyncCallBack
|
||||
// Secondary storage resource usage will be incremented in com.cloud.template.HypervisorTemplateAdapter.createTemplateAsyncCallBack
|
||||
// for HypervisorTemplateAdapter
|
||||
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
|
||||
if (secondaryStorageUsage > 0) {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import javax.naming.ConfigurationException;
|
|||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import com.cloud.resourcelimit.ReservationHelper;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
|
|
@ -122,6 +123,7 @@ import org.apache.cloudstack.framework.messagebus.PublishScope;
|
|||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.query.QueryService;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.snapshot.SnapshotHelper;
|
||||
import org.apache.cloudstack.storage.command.DeleteCommand;
|
||||
import org.apache.cloudstack.storage.command.DettachCommand;
|
||||
|
|
@ -1351,9 +1353,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
Account owner = _accountMgr.getActiveAccountById(vmInstance.getAccountId());
|
||||
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vmInstance.getTemplateId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
if (!VirtualMachineManager.ResourceCountRunningVMsonly.value()) {
|
||||
_resourceLimitMgr.checkVmResourceLimitsForServiceOfferingChange(owner, vmInstance.isDisplay(), (long) currentCpu, (long) newCpu,
|
||||
(long) currentMemory, (long) newMemory, currentServiceOffering, newServiceOffering, template);
|
||||
(long) currentMemory, (long) newMemory, currentServiceOffering, newServiceOffering, template, reservations);
|
||||
}
|
||||
|
||||
// Check that the specified service offering ID is valid
|
||||
|
|
@ -1376,6 +1381,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
return _vmDao.findById(vmInstance.getId());
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2063,9 +2071,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vmInstance.getTemplateId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
// Check resource limits
|
||||
_resourceLimitMgr.checkVmResourceLimitsForServiceOfferingChange(owner, vmInstance.isDisplay(), (long) currentCpu, (long) newCpu,
|
||||
(long) currentMemory, (long) newMemory, currentServiceOffering, newServiceOffering, template);
|
||||
(long) currentMemory, (long) newMemory, currentServiceOffering, newServiceOffering, template, reservations);
|
||||
|
||||
// Dynamically upgrade the running vms
|
||||
boolean success = false;
|
||||
|
|
@ -2137,6 +2147,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
}
|
||||
return success;
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateDiskOfferingChecks(ServiceOfferingVO currentServiceOffering, ServiceOfferingVO newServiceOffering) {
|
||||
|
|
@ -2322,10 +2336,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
|
||||
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
// First check that the maximum number of UserVMs, CPU and Memory limit for the given
|
||||
// accountId will not be exceeded
|
||||
if (!VirtualMachineManager.ResourceCountRunningVMsonly.value()) {
|
||||
resourceLimitService.checkVmResourceLimit(account, vm.isDisplayVm(), serviceOffering, template);
|
||||
resourceLimitService.checkVmResourceLimit(account, vm.isDisplayVm(), serviceOffering, template, reservations);
|
||||
}
|
||||
|
||||
_haMgr.cancelDestroy(vm, vm.getHostId());
|
||||
|
|
@ -2350,6 +2366,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
//Update Resource Count for the given account
|
||||
resourceCountIncrement(account.getId(), vm.isDisplayVm(), serviceOffering, template);
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -2776,27 +2796,25 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
long currentCpu = currentServiceOffering.getCpu();
|
||||
long currentMemory = currentServiceOffering.getRamSize();
|
||||
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vmInstance.getTemplateId());
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
_resourceLimitMgr.checkVmResourceLimitsForServiceOfferingChange(owner, vmInstance.isDisplay(), currentCpu, newCpu,
|
||||
currentMemory, newMemory, currentServiceOffering, svcOffering, template, reservations);
|
||||
if (newCpu > currentCpu) {
|
||||
_resourceLimitMgr.checkVmCpuResourceLimit(owner, vmInstance.isDisplay(), svcOffering, template, newCpu - currentCpu);
|
||||
_resourceLimitMgr.incrementVmCpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newCpu - currentCpu);
|
||||
} else if (newCpu > 0 && currentCpu > newCpu){
|
||||
_resourceLimitMgr.decrementVmCpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentCpu - newCpu);
|
||||
}
|
||||
if (newMemory > currentMemory) {
|
||||
_resourceLimitMgr.checkVmMemoryResourceLimit(owner, vmInstance.isDisplay(), svcOffering, template, newMemory - currentMemory);
|
||||
_resourceLimitMgr.incrementVmMemoryResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newMemory - currentMemory);
|
||||
} else if (newMemory > 0 && currentMemory > newMemory){
|
||||
_resourceLimitMgr.decrementVmMemoryResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentMemory - newMemory);
|
||||
}
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error(String.format("Failed to updated VM due to: %s", e.getLocalizedMessage()));
|
||||
throw new InvalidParameterValueException(e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
if (newCpu > currentCpu) {
|
||||
_resourceLimitMgr.incrementVmCpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newCpu - currentCpu);
|
||||
} else if (newCpu > 0 && currentCpu > newCpu){
|
||||
_resourceLimitMgr.decrementVmCpuResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentCpu - newCpu);
|
||||
}
|
||||
if (newMemory > currentMemory) {
|
||||
_resourceLimitMgr.incrementVmMemoryResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, newMemory - currentMemory);
|
||||
} else if (newMemory > 0 && currentMemory > newMemory){
|
||||
_resourceLimitMgr.decrementVmMemoryResourceCount(owner.getAccountId(), vmInstance.isDisplay(), svcOffering, template, currentMemory - newMemory);
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4236,7 +4254,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
throw new InvalidParameterValueException(String.format("Invalid disk offering %s specified for datadisk Template %s. Disk offering size should be greater than or equal to the Template size", dataDiskOffering, dataDiskTemplate));
|
||||
}
|
||||
_templateDao.loadDetails(dataDiskTemplate);
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, dataDiskOffering.getDiskSize(), dataDiskOffering);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5660,11 +5677,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
CheckedReservation memReservation = new CheckedReservation(owner, ResourceType.memory, resourceLimitHostTags, Long.valueOf(offering.getRamSize()), reservationDao, resourceLimitService);
|
||||
) {
|
||||
return startVirtualMachineUnchecked(vm, template, podId, clusterId, hostId, additionalParams, deploymentPlannerToUse, isExplicitHost, isRootAdmin);
|
||||
} catch (ResourceAllocationException | CloudRuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to start VM {} : error during resource reservation and allocation", e);
|
||||
throw new CloudRuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
return startVirtualMachineUnchecked(vm, template, podId, clusterId, hostId, additionalParams, deploymentPlannerToUse, isExplicitHost, isRootAdmin);
|
||||
|
|
@ -7387,38 +7399,29 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return findMigratedVm(vm.getId(), vm.getType());
|
||||
}
|
||||
|
||||
protected void checkVolumesLimits(Account account, List<VolumeVO> volumes) throws ResourceAllocationException {
|
||||
Long totalVolumes = 0L;
|
||||
Long totalVolumesSize = 0L;
|
||||
protected void checkVolumesLimits(Account account, List<VolumeVO> volumes, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
Map<Long, List<String>> diskOfferingTagsMap = new HashMap<>();
|
||||
Map<String, Long> tagVolumeCountMap = new HashMap<>();
|
||||
Map<String, Long> tagSizeMap = new HashMap<>();
|
||||
|
||||
for (VolumeVO volume : volumes) {
|
||||
if (!volume.isDisplay()) {
|
||||
continue;
|
||||
}
|
||||
totalVolumes++;
|
||||
totalVolumesSize += volume.getSize();
|
||||
if (!diskOfferingTagsMap.containsKey(volume.getDiskOfferingId())) {
|
||||
diskOfferingTagsMap.put(volume.getDiskOfferingId(), _resourceLimitMgr.getResourceLimitStorageTags(
|
||||
_diskOfferingDao.findById(volume.getDiskOfferingId())));
|
||||
|
||||
Long diskOfferingId = volume.getDiskOfferingId();
|
||||
if (!diskOfferingTagsMap.containsKey(diskOfferingId)) {
|
||||
DiskOffering diskOffering = _diskOfferingDao.findById(diskOfferingId);
|
||||
List<String> tagsForDiskOffering = _resourceLimitMgr.getResourceLimitStorageTags(diskOffering);
|
||||
diskOfferingTagsMap.put(diskOfferingId, tagsForDiskOffering);
|
||||
}
|
||||
List<String> tags = diskOfferingTagsMap.get(volume.getDiskOfferingId());
|
||||
for (String tag : tags) {
|
||||
if (tagVolumeCountMap.containsKey(tag)) {
|
||||
tagVolumeCountMap.put(tag, tagVolumeCountMap.get(tag) + 1);
|
||||
tagSizeMap.put(tag, tagSizeMap.get(tag) + volume.getSize());
|
||||
} else {
|
||||
tagVolumeCountMap.put(tag, 1L);
|
||||
tagSizeMap.put(tag, volume.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
_resourceLimitMgr.checkResourceLimit(account, ResourceType.volume, totalVolumes);
|
||||
_resourceLimitMgr.checkResourceLimit(account, ResourceType.primary_storage, totalVolumesSize);
|
||||
for (String tag : tagVolumeCountMap.keySet()) {
|
||||
resourceLimitService.checkResourceLimitWithTag(account, ResourceType.volume, tag, tagVolumeCountMap.get(tag));
|
||||
resourceLimitService.checkResourceLimitWithTag(account, ResourceType.primary_storage, tag, tagSizeMap.get(tag));
|
||||
|
||||
List<String> tags = diskOfferingTagsMap.get(diskOfferingId);
|
||||
|
||||
CheckedReservation volumeReservation = new CheckedReservation(account, ResourceType.volume, tags, 1L, reservationDao, resourceLimitService);
|
||||
reservations.add(volumeReservation);
|
||||
|
||||
long size = ObjectUtils.defaultIfNull(volume.getSize(), 0L);
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(account, ResourceType.primary_storage, tags, size, reservationDao, resourceLimitService);
|
||||
reservations.add(primaryStorageReservation);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7460,14 +7463,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
final ServiceOfferingVO offering = serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId());
|
||||
VirtualMachineTemplate template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
|
||||
|
||||
verifyResourceLimitsForAccountAndStorage(newAccount, vm, offering, volumes, template);
|
||||
|
||||
validateIfNewOwnerHasAccessToTemplate(vm, newAccount, template);
|
||||
|
||||
DomainVO domain = _domainDao.findById(domainId);
|
||||
logger.trace("Verifying if the new account [{}] has access to the specified domain [{}].", newAccount, domain);
|
||||
_accountMgr.checkAccess(newAccount, domain);
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
verifyResourceLimitsForAccountAndStorage(newAccount, vm, offering, volumes, template, reservations);
|
||||
|
||||
Network newNetwork = ensureDestinationNetwork(cmd, vm, newAccount);
|
||||
try {
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
|
|
@ -7484,6 +7489,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
throw e;
|
||||
}
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
|
||||
logger.info("VM [{}] now belongs to account [{}].", vm.getInstanceName(), newAccountName);
|
||||
return vm;
|
||||
}
|
||||
|
|
@ -7554,18 +7563,18 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
* @param volumes The volumes whose total size can exceed resource limits.
|
||||
* @throws ResourceAllocationException
|
||||
*/
|
||||
protected void verifyResourceLimitsForAccountAndStorage(Account account, UserVmVO vm, ServiceOfferingVO offering, List<VolumeVO> volumes, VirtualMachineTemplate template)
|
||||
protected void verifyResourceLimitsForAccountAndStorage(Account account, UserVmVO vm, ServiceOfferingVO offering, List<VolumeVO> volumes, VirtualMachineTemplate template, List<Reserver> reservations)
|
||||
throws ResourceAllocationException {
|
||||
|
||||
logger.trace("Verifying if CPU and RAM for VM [{}] do not exceed account [{}] limit.", vm, account);
|
||||
|
||||
if (!countOnlyRunningVmsInResourceLimitation()) {
|
||||
resourceLimitService.checkVmResourceLimit(account, vm.isDisplayVm(), offering, template);
|
||||
resourceLimitService.checkVmResourceLimit(account, vm.isDisplayVm(), offering, template, reservations);
|
||||
}
|
||||
|
||||
logger.trace("Verifying if volume size for VM [{}] does not exceed account [{}] limit.", vm, account);
|
||||
|
||||
checkVolumesLimits(account, volumes);
|
||||
checkVolumesLimits(account, volumes, reservations);
|
||||
}
|
||||
|
||||
protected boolean countOnlyRunningVmsInResourceLimitation() {
|
||||
|
|
@ -8415,12 +8424,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
VMTemplateVO template = getRestoreVirtualMachineTemplate(caller, newTemplateId, rootVols, vm);
|
||||
DiskOffering diskOffering = rootDiskOfferingId != null ? _diskOfferingDao.findById(rootDiskOfferingId) : null;
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
checkRestoreVmFromTemplate(vm, template, rootVols, diskOffering, details);
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("Failed to restore VM {} due to {}", vm, e.getMessage(), e);
|
||||
throw new CloudRuntimeException("Failed to restore VM " + vm.getUuid() + " due to " + e.getMessage(), e);
|
||||
}
|
||||
checkRestoreVmFromTemplate(vm, template, rootVols, diskOffering, details, reservations);
|
||||
|
||||
if (needRestart) {
|
||||
try {
|
||||
|
|
@ -8565,6 +8572,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
logger.debug("Restore VM {} done successfully", vm);
|
||||
return vm;
|
||||
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("Failed to restore VM {} due to {}", vm, e.getMessage(), e);
|
||||
throw new CloudRuntimeException("Failed to restore VM " + vm.getUuid() + " due to " + e.getMessage(), e);
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
Long getRootVolumeSizeForVmRestore(Volume vol, VMTemplateVO template, UserVmVO userVm, DiskOffering diskOffering, Map<String, String> details, boolean update) {
|
||||
|
|
@ -8664,7 +8677,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
* @param template template
|
||||
* @throws InvalidParameterValueException if restore is not possible
|
||||
*/
|
||||
private void checkRestoreVmFromTemplate(UserVmVO vm, VMTemplateVO template, List<VolumeVO> rootVolumes, DiskOffering newDiskOffering, Map<String,String> details) throws ResourceAllocationException {
|
||||
private void checkRestoreVmFromTemplate(UserVmVO vm, VMTemplateVO template, List<VolumeVO> rootVolumes, DiskOffering newDiskOffering, Map<String,String> details, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
TemplateDataStoreVO tmplStore;
|
||||
if (!template.isDirectDownload()) {
|
||||
tmplStore = _templateStoreDao.findByTemplateZoneReady(template.getId(), vm.getDataCenterId());
|
||||
|
|
@ -8682,7 +8695,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (vm.getTemplateId() != template.getId()) {
|
||||
ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
|
||||
VMTemplateVO currentTemplate = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
|
||||
_resourceLimitMgr.checkVmResourceLimitsForTemplateChange(owner, vm.isDisplay(), serviceOffering, currentTemplate, template);
|
||||
_resourceLimitMgr.checkVmResourceLimitsForTemplateChange(owner, vm.isDisplay(), serviceOffering, currentTemplate, template, reservations);
|
||||
}
|
||||
|
||||
for (Volume vol : rootVolumes) {
|
||||
|
|
@ -8693,7 +8706,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (newDiskOffering != null || !vol.getSize().equals(newSize)) {
|
||||
DiskOffering currentOffering = _diskOfferingDao.findById(vol.getDiskOfferingId());
|
||||
_resourceLimitMgr.checkVolumeResourceLimitForDiskOfferingChange(owner, vol.isDisplay(),
|
||||
vol.getSize(), newSize, currentOffering, newDiskOffering);
|
||||
vol.getSize(), newSize, currentOffering, newDiskOffering, reservations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -811,25 +811,31 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
}
|
||||
|
||||
/**
|
||||
* If snapshot was taken with a different service offering than actual used in vm, should change it back to it
|
||||
* @param userVm vm to change service offering (if necessary)
|
||||
* If snapshot was taken with a different service offering than actual used in vm, should change it back to it.
|
||||
* We also call <code>changeUserVmServiceOffering</code> in case the service offering is dynamic in order to
|
||||
* perform resource limit validation, as the amount of CPUs or memory may have been changed.
|
||||
* @param vmSnapshotVo vm snapshot
|
||||
*/
|
||||
protected void updateUserVmServiceOffering(UserVm userVm, VMSnapshotVO vmSnapshotVo) {
|
||||
if (vmSnapshotVo.getServiceOfferingId() != userVm.getServiceOfferingId()) {
|
||||
changeUserVmServiceOffering(userVm, vmSnapshotVo);
|
||||
return;
|
||||
}
|
||||
ServiceOfferingVO serviceOffering = _serviceOfferingDao.findById(userVm.getServiceOfferingId());
|
||||
if (serviceOffering.isDynamic()) {
|
||||
changeUserVmServiceOffering(userVm, vmSnapshotVo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user vm details as a map
|
||||
* @param userVm user vm
|
||||
* @param vmSnapshotVo snapshot to get the details from
|
||||
* @return map
|
||||
*/
|
||||
protected Map<String, String> getVmMapDetails(UserVm userVm) {
|
||||
List<UserVmDetailVO> userVmDetails = _userVmDetailsDao.listDetails(userVm.getId());
|
||||
protected Map<String, String> getVmMapDetails(VMSnapshotVO vmSnapshotVo) {
|
||||
List<VMSnapshotDetailsVO> vmSnapshotDetails = _vmSnapshotDetailsDao.listDetails(vmSnapshotVo.getId());
|
||||
Map<String, String> details = new HashMap<String, String>();
|
||||
for (UserVmDetailVO detail : userVmDetails) {
|
||||
for (VMSnapshotDetailsVO detail : vmSnapshotDetails) {
|
||||
details.put(detail.getName(), detail.getValue());
|
||||
}
|
||||
return details;
|
||||
|
|
@ -841,7 +847,7 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
* @param vmSnapshotVo vm snapshot
|
||||
*/
|
||||
protected void changeUserVmServiceOffering(UserVm userVm, VMSnapshotVO vmSnapshotVo) {
|
||||
Map<String, String> vmDetails = getVmMapDetails(userVm);
|
||||
Map<String, String> vmDetails = getVmMapDetails(vmSnapshotVo);
|
||||
boolean result = upgradeUserVmServiceOffering(userVm, vmSnapshotVo.getServiceOfferingId(), vmDetails);
|
||||
if (! result){
|
||||
throw new CloudRuntimeException("Instance Snapshot reverting failed because the Instance service offering couldn't be changed to the one used when Snapshot was taken");
|
||||
|
|
@ -938,8 +944,8 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<CloudRuntimeException>() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) throws CloudRuntimeException {
|
||||
revertCustomServiceOfferingDetailsFromVmSnapshot(userVm, vmSnapshotVo);
|
||||
updateUserVmServiceOffering(userVm, vmSnapshotVo);
|
||||
revertCustomServiceOfferingDetailsFromVmSnapshot(userVm, vmSnapshotVo);
|
||||
}
|
||||
});
|
||||
return userVm;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import com.cloud.host.HostVO;
|
|||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.resourcelimit.ReservationHelper;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.Storage;
|
||||
|
|
@ -68,6 +69,7 @@ import org.apache.cloudstack.api.response.VolumeForImportResponse;
|
|||
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
|
|
@ -198,10 +200,7 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ
|
|||
logFailureAndThrowException("Volume is a reference of snapshot on primary: " + volume.getFullPath());
|
||||
}
|
||||
|
||||
// 5. check resource limitation
|
||||
checkResourceLimitForImportVolume(owner, volume);
|
||||
|
||||
// 6. get disk offering
|
||||
// 5. get disk offering
|
||||
DiskOfferingVO diskOffering = getOrCreateDiskOffering(owner, cmd.getDiskOfferingId(), pool.getDataCenterId(), pool.isLocal());
|
||||
if (diskOffering.isCustomized()) {
|
||||
volumeApiService.validateCustomDiskOfferingSizeRange(volume.getVirtualSize() / ByteScaleUtils.GiB);
|
||||
|
|
@ -210,6 +209,11 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ
|
|||
logFailureAndThrowException(String.format("Disk offering: %s storage tags are not compatible with selected storage pool: %s", diskOffering, pool));
|
||||
}
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
// 6. check resource limitation
|
||||
checkResourceLimitForImportVolume(owner, volume, diskOffering, reservations);
|
||||
|
||||
// 7. create records
|
||||
String volumeName = StringUtils.isNotBlank(cmd.getName()) ? cmd.getName().trim() : volumePath;
|
||||
VolumeVO volumeVO = importVolumeInternal(volume, diskOffering, owner, pool, volumeName);
|
||||
|
|
@ -221,6 +225,10 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ
|
|||
publicUsageEventForVolumeImportAndUnmanage(volumeVO, true);
|
||||
|
||||
return responseGenerator.createVolumeResponse(ResponseObject.ResponseView.Full, volumeVO);
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
protected VolumeOnStorageTO getVolumeOnStorageAndCheck(StoragePoolVO pool, String volumePath) {
|
||||
|
|
@ -456,11 +464,10 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ
|
|||
return volumeDao.findById(diskProfile.getVolumeId());
|
||||
}
|
||||
|
||||
protected void checkResourceLimitForImportVolume(Account owner, VolumeOnStorageTO volume) {
|
||||
protected void checkResourceLimitForImportVolume(Account owner, VolumeOnStorageTO volume, DiskOfferingVO diskOffering, List<Reserver> reservations) {
|
||||
Long volumeSize = volume.getVirtualSize();
|
||||
try {
|
||||
resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume);
|
||||
resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.primary_storage, volumeSize);
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, volumeSize, diskOffering, reservations);
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("VM resource allocation error for account: {}", owner, e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ import com.cloud.offerings.dao.NetworkOfferingDao;
|
|||
import com.cloud.org.Cluster;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resource.ResourceState;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.resourcelimit.ReservationHelper;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
|
|
@ -164,6 +166,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
|
|
@ -222,6 +226,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
@Inject
|
||||
private ResourceLimitService resourceLimitService;
|
||||
@Inject
|
||||
private ReservationDao reservationDao;
|
||||
@Inject
|
||||
private UserVmDetailsDao userVmDetailsDao;
|
||||
@Inject
|
||||
private UserVmManager userVmManager;
|
||||
|
|
@ -604,7 +610,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
return new Pair<>(rootDisk, dataDisks);
|
||||
}
|
||||
|
||||
private void checkUnmanagedDiskAndOfferingForImport(String instanceName, UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed)
|
||||
private void checkUnmanagedDiskAndOfferingForImport(String instanceName, UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List<Reserver> reservations)
|
||||
throws ServerApiException, PermissionDeniedException, ResourceAllocationException {
|
||||
if (serviceOffering == null && diskOffering == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID [%s] not found during VM [%s] import.", disk.getDiskId(), instanceName));
|
||||
|
|
@ -612,7 +618,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
if (diskOffering != null) {
|
||||
accountService.checkAccess(owner, diskOffering, zone);
|
||||
}
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, null, diskOffering);
|
||||
if (disk.getCapacity() == null || disk.getCapacity() == 0) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk(ID: %s) is found invalid during VM import", disk.getDiskId()));
|
||||
}
|
||||
|
|
@ -627,9 +632,10 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
if (diskOffering != null && !migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) {
|
||||
throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId()));
|
||||
}
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), diskOffering, reservations);
|
||||
}
|
||||
|
||||
private void checkUnmanagedDiskAndOfferingForImport(String intanceName, List<UnmanagedInstanceTO.Disk> disks, final Map<String, Long> diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed)
|
||||
private void checkUnmanagedDiskAndOfferingForImport(String intanceName, List<UnmanagedInstanceTO.Disk> disks, final Map<String, Long> diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List<Reserver> reservations)
|
||||
throws ServerApiException, PermissionDeniedException, ResourceAllocationException {
|
||||
String diskController = null;
|
||||
for (UnmanagedInstanceTO.Disk disk : disks) {
|
||||
|
|
@ -646,7 +652,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple data disk controllers of different type (%s, %s) are not supported for import. Please make sure that all data disk controllers are of the same type", diskController, disk.getController()));
|
||||
}
|
||||
}
|
||||
checkUnmanagedDiskAndOfferingForImport(intanceName, disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), null, owner, zone, cluster, migrateAllowed);
|
||||
checkUnmanagedDiskAndOfferingForImport(intanceName, disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), null, owner, zone, cluster, migrateAllowed, reservations);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1073,40 +1079,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
}
|
||||
}
|
||||
|
||||
protected void checkUnmanagedDiskLimits(Account account, UnmanagedInstanceTO.Disk rootDisk, ServiceOffering serviceOffering,
|
||||
List<UnmanagedInstanceTO.Disk> dataDisks, Map<String, Long> dataDiskOfferingMap) throws ResourceAllocationException {
|
||||
Long totalVolumes = 0L;
|
||||
Long totalVolumesSize = 0L;
|
||||
List<UnmanagedInstanceTO.Disk> disks = new ArrayList<>();
|
||||
disks.add(rootDisk);
|
||||
disks.addAll(dataDisks);
|
||||
Map<String, Long> diskOfferingMap = new HashMap<>(dataDiskOfferingMap);
|
||||
diskOfferingMap.put(rootDisk.getDiskId(), serviceOffering.getDiskOfferingId());
|
||||
Map<Long, Long> diskOfferingVolumeCountMap = new HashMap<>();
|
||||
Map<Long, Long> diskOfferingSizeMap = new HashMap<>();
|
||||
for (UnmanagedInstanceTO.Disk disk : disks) {
|
||||
totalVolumes++;
|
||||
totalVolumesSize += disk.getCapacity();
|
||||
Long diskOfferingId = diskOfferingMap.get(disk.getDiskId());
|
||||
if (diskOfferingVolumeCountMap.containsKey(diskOfferingId)) {
|
||||
diskOfferingVolumeCountMap.put(diskOfferingId, diskOfferingVolumeCountMap.get(diskOfferingId) + 1);
|
||||
diskOfferingSizeMap.put(diskOfferingId, diskOfferingSizeMap.get(diskOfferingId) + disk.getCapacity());
|
||||
} else {
|
||||
diskOfferingVolumeCountMap.put(diskOfferingId, 1L);
|
||||
diskOfferingSizeMap.put(diskOfferingId, disk.getCapacity());
|
||||
}
|
||||
}
|
||||
resourceLimitService.checkResourceLimit(account, Resource.ResourceType.volume, totalVolumes);
|
||||
resourceLimitService.checkResourceLimit(account, Resource.ResourceType.primary_storage, totalVolumesSize);
|
||||
for (Long diskOfferingId : diskOfferingVolumeCountMap.keySet()) {
|
||||
List<String> tags = resourceLimitService.getResourceLimitStorageTags(diskOfferingDao.findById(diskOfferingId));
|
||||
for (String tag : tags) {
|
||||
resourceLimitService.checkResourceLimitWithTag(account, Resource.ResourceType.volume, tag, diskOfferingVolumeCountMap.get(diskOfferingId));
|
||||
resourceLimitService.checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, tag, diskOfferingSizeMap.get(diskOfferingId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedInstance, final String instanceNameInternal, final DataCenter zone, final Cluster cluster, final HostVO host,
|
||||
final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId,
|
||||
final ServiceOfferingVO serviceOffering, final Map<String, Long> dataDiskOfferingMap,
|
||||
|
|
@ -1164,17 +1136,14 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
allDetails.put(VmDetailConstants.ROOT_DISK_SIZE, String.valueOf(size));
|
||||
}
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed);
|
||||
if (CollectionUtils.isNotEmpty(dataDisks)) { // Data disk(s) present
|
||||
checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed);
|
||||
allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController());
|
||||
}
|
||||
checkUnmanagedDiskLimits(owner, rootDisk, serviceOffering, dataDisks, dataDiskOfferingMap);
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("Volume resource allocation error for owner: {}", owner, e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed, reservations);
|
||||
if (CollectionUtils.isNotEmpty(dataDisks)) { // Data disk(s) present
|
||||
checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed, reservations);
|
||||
allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController());
|
||||
}
|
||||
|
||||
// Check NICs and supplied networks
|
||||
Map<String, Network.IpAddresses> nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap);
|
||||
Map<String, Long> allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, cluster.getHypervisorType());
|
||||
|
|
@ -1257,6 +1226,13 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
}
|
||||
publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering, template);
|
||||
return userVm;
|
||||
|
||||
} catch (ResourceAllocationException e) { // This will be thrown by checkUnmanagedDiskAndOfferingForImport, so the VM was not imported yet
|
||||
logger.error("Volume resource allocation error for owner: {}", owner, e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
private void addImportingVMBootTypeAndModeDetails(String bootType, String bootMode, Map<String, String> allDetails) {
|
||||
|
|
@ -1361,8 +1337,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
VMTemplateVO template = getTemplateForImportInstance(cmd.getTemplateId(), cluster.getHypervisorType());
|
||||
ServiceOfferingVO serviceOffering = getServiceOfferingForImportInstance(cmd.getServiceOfferingId(), owner, zone);
|
||||
|
||||
checkResourceLimitForImportInstance(owner);
|
||||
|
||||
String displayName = getDisplayNameForImportInstance(cmd.getDisplayName(), instanceName);
|
||||
String hostName = getHostNameForImportInstance(cmd.getHostName(), cluster.getHypervisorType(), instanceName, displayName);
|
||||
|
||||
|
|
@ -1378,6 +1352,11 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
List<String> managedVms = new ArrayList<>(additionalNameFilters);
|
||||
managedVms.addAll(getHostsManagedVms(hosts));
|
||||
|
||||
List<String> resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template);
|
||||
try (CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService);
|
||||
CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, Long.valueOf(serviceOffering.getCpu()), reservationDao, resourceLimitService);
|
||||
CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, Long.valueOf(serviceOffering.getRamSize()), reservationDao, resourceLimitService)) {
|
||||
|
||||
ActionEventUtils.onStartedActionEvent(userId, owner.getId(), EventTypes.EVENT_VM_IMPORT,
|
||||
cmd.getEventDescription(), null, null, true, 0);
|
||||
|
||||
|
|
@ -1405,6 +1384,11 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
}
|
||||
}
|
||||
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error(String.format("VM resource allocation error for account: %s", owner.getUuid()), e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
|
||||
if (userVm == null) {
|
||||
ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_IMPORT,
|
||||
cmd.getEventDescription(), null, null, 0);
|
||||
|
|
@ -1464,15 +1448,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
return StringUtils.isEmpty(displayName) ? instanceName : displayName;
|
||||
}
|
||||
|
||||
private void checkResourceLimitForImportInstance(Account owner) {
|
||||
try {
|
||||
resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.user_vm, 1);
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("VM resource allocation error for account: {}", owner, e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
}
|
||||
|
||||
private ServiceOfferingVO getServiceOfferingForImportInstance(Long serviceOfferingId, Account owner, DataCenter zone) {
|
||||
if (serviceOfferingId == null) {
|
||||
throw new InvalidParameterValueException("Service offering ID cannot be null");
|
||||
|
|
@ -2338,12 +2313,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
throw new InvalidParameterValueException(String.format("Service offering ID: %d cannot be found", serviceOfferingId));
|
||||
}
|
||||
accountService.checkAccess(owner, serviceOffering, zone);
|
||||
try {
|
||||
resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.user_vm, 1);
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error("VM resource allocation error for account: {}", owner, e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
String displayName = cmd.getDisplayName();
|
||||
if (StringUtils.isEmpty(displayName)) {
|
||||
displayName = instanceName;
|
||||
|
|
@ -2431,6 +2400,11 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
|
||||
UserVm userVm = null;
|
||||
|
||||
List<String> resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template);
|
||||
try (CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService);
|
||||
CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, Long.valueOf(serviceOffering.getCpu()), reservationDao, resourceLimitService);
|
||||
CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, Long.valueOf(serviceOffering.getRamSize()), reservationDao, resourceLimitService)) {
|
||||
|
||||
if (ImportSource.EXTERNAL == importSource) {
|
||||
String username = cmd.getUsername();
|
||||
String password = cmd.getPassword();
|
||||
|
|
@ -2451,6 +2425,12 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ResourceAllocationException e) {
|
||||
logger.error(String.format("VM resource allocation error for account: %s", owner.getUuid()), e);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
|
||||
if (userVm == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import Vm with name: %s ", instanceName));
|
||||
}
|
||||
|
|
@ -2464,7 +2444,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId,
|
||||
final ServiceOfferingVO serviceOffering, final Map<String, Long> dataDiskOfferingMap,
|
||||
final Map<String, Long> nicNetworkMap, final Map<String, Network.IpAddresses> callerNicIpAddressMap,
|
||||
final String remoteUrl, String username, String password, String tmpPath, final Map<String, String> details) {
|
||||
final String remoteUrl, String username, String password, String tmpPath, final Map<String, String> details) throws ResourceAllocationException {
|
||||
UserVm userVm = null;
|
||||
|
||||
Map<String, String> allDetails = new HashMap<>(details);
|
||||
|
|
@ -2475,6 +2455,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("No attached disks found for the unmanaged VM: %s", instanceName));
|
||||
}
|
||||
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
||||
Pair<UnmanagedInstanceTO.Disk, List<UnmanagedInstanceTO.Disk>> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap);
|
||||
final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first();
|
||||
final List<UnmanagedInstanceTO.Disk> dataDisks = rootAndDataDisksPair.second();
|
||||
|
|
@ -2483,6 +2464,10 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
}
|
||||
allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
try {
|
||||
checkVolumeResourceLimitsForExternalKvmVmImport(owner, rootDisk, dataDisks, diskOffering, dataDiskOfferingMap, reservations);
|
||||
|
||||
// Check NICs and supplied networks
|
||||
Map<String, Network.IpAddresses> nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap);
|
||||
Map<String, Long> allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, Hypervisor.HypervisorType.KVM);
|
||||
|
|
@ -2503,16 +2488,12 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
if (userVm == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", instanceName));
|
||||
}
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
||||
String rootVolumeName = String.format("ROOT-%s", userVm.getId());
|
||||
DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null);
|
||||
|
||||
DiskProfile[] dataDiskProfiles = new DiskProfile[dataDisks.size()];
|
||||
int diskSeq = 0;
|
||||
for (UnmanagedInstanceTO.Disk disk : dataDisks) {
|
||||
if (disk.getCapacity() == null || disk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", disk.getDiskId()));
|
||||
}
|
||||
DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId()));
|
||||
DiskProfile dataDiskProfile = volumeManager.allocateRawVolume(Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), offering, null, null, null, userVm, template, owner, null);
|
||||
dataDiskProfiles[diskSeq++] = dataDiskProfile;
|
||||
|
|
@ -2537,10 +2518,6 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
|
||||
List<Pair<DiskProfile, StoragePool>> diskProfileStoragePoolList = new ArrayList<>();
|
||||
try {
|
||||
if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId()));
|
||||
}
|
||||
|
||||
diskProfileStoragePoolList.add(importExternalDisk(rootDisk, userVm, dest, diskOffering, Volume.Type.ROOT,
|
||||
template, null, remoteUrl, username, password, tmpPath, diskProfile));
|
||||
|
||||
|
|
@ -2574,6 +2551,30 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
}
|
||||
publishVMUsageUpdateResourceCount(userVm, dummyOffering, template);
|
||||
return userVm;
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkVolumeResourceLimitsForExternalKvmVmImport(Account owner, UnmanagedInstanceTO.Disk rootDisk,
|
||||
List<UnmanagedInstanceTO.Disk> dataDisks, DiskOfferingVO rootDiskOffering,
|
||||
Map<String, Long> dataDiskOfferingMap, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId()));
|
||||
}
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, rootDisk.getCapacity(), rootDiskOffering, reservations);
|
||||
|
||||
if (CollectionUtils.isEmpty(dataDisks)) {
|
||||
return;
|
||||
}
|
||||
for (UnmanagedInstanceTO.Disk disk : dataDisks) {
|
||||
if (disk.getCapacity() == null || disk.getCapacity() == 0) {
|
||||
throw new InvalidParameterValueException(String.format("Data disk ID: %s size is invalid", disk.getDiskId()));
|
||||
}
|
||||
DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId()));
|
||||
resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), offering, reservations);
|
||||
}
|
||||
}
|
||||
|
||||
private UserVm importKvmVirtualMachineFromDisk(final ImportSource importSource, final String instanceName, final DataCenter zone,
|
||||
|
|
@ -2641,7 +2642,16 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
if (userVm == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", instanceName));
|
||||
}
|
||||
|
||||
DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
|
||||
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
List<String> resourceLimitStorageTags = resourceLimitService.getResourceLimitStorageTagsForResourceCountOperation(true, diskOffering);
|
||||
try {
|
||||
CheckedReservation volumeReservation = new CheckedReservation(owner, Resource.ResourceType.volume, resourceLimitStorageTags,
|
||||
CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? 1L : 0L, reservationDao, resourceLimitService);
|
||||
reservations.add(volumeReservation);
|
||||
|
||||
String rootVolumeName = String.format("ROOT-%s", userVm.getId());
|
||||
DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null);
|
||||
|
||||
|
|
@ -2686,6 +2696,14 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
throw new CloudRuntimeException("Disk not found or is invalid");
|
||||
}
|
||||
diskProfile.setSize(checkVolumeAnswer.getSize());
|
||||
try {
|
||||
CheckedReservation primaryStorageReservation = new CheckedReservation(owner, Resource.ResourceType.primary_storage, resourceLimitStorageTags,
|
||||
CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? diskProfile.getSize() : 0L, reservationDao, resourceLimitService);
|
||||
reservations.add(primaryStorageReservation);
|
||||
} catch (ResourceAllocationException e) {
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw e;
|
||||
}
|
||||
|
||||
List<Pair<DiskProfile, StoragePool>> diskProfileStoragePoolList = new ArrayList<>();
|
||||
try {
|
||||
|
|
@ -2705,6 +2723,10 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
networkOrchestrationService.importNic(macAddress, 0, network, true, userVm, requestedIpPair, zone, true);
|
||||
publishVMUsageUpdateResourceCount(userVm, dummyOffering, template);
|
||||
return userVm;
|
||||
|
||||
} finally {
|
||||
ReservationHelper.closeAll(reservations);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkVolume(Map<VolumeOnStorageTO.Detail, String> volumeDetails) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import org.apache.cloudstack.api.response.DomainResponse;
|
|||
import org.apache.cloudstack.api.response.TaggedResourceLimitAndCountResponse;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.reservation.dao.ReservationDao;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
|
@ -40,6 +41,7 @@ import org.junit.Test;
|
|||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedConstruction;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
|
@ -264,6 +266,7 @@ public class ResourceLimitManagerImplTest extends TestCase {
|
|||
|
||||
@Test
|
||||
public void testCheckVmResourceLimit() {
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
|
||||
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
|
||||
Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
|
||||
|
|
@ -271,53 +274,12 @@ public class ResourceLimitManagerImplTest extends TestCase {
|
|||
Mockito.when(serviceOffering.getRamSize()).thenReturn(256);
|
||||
Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
|
||||
Account account = Mockito.mock(Account.class);
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
resourceLimitManager.checkVmResourceLimit(account, true, serviceOffering, template);
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
resourceLimitManager.checkVmResourceLimit(account, true, serviceOffering, template, reservations);
|
||||
List<String> tags = new ArrayList<>();
|
||||
tags.add(null);
|
||||
tags.add(hostTags.get(0));
|
||||
for (String tag: tags) {
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.user_vm, tag);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.cpu, tag, 2L);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.memory, tag, 256L);
|
||||
}
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckVmCpuResourceLimit() {
|
||||
ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
|
||||
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
|
||||
Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
|
||||
Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
|
||||
Account account = Mockito.mock(Account.class);
|
||||
long cpu = 2L;
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
resourceLimitManager.checkVmCpuResourceLimit(account, true, serviceOffering, template, cpu);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.cpu, null, cpu);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.cpu, hostTags.get(0), cpu);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckVmMemoryResourceLimit() {
|
||||
ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
|
||||
VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class);
|
||||
Mockito.when(serviceOffering.getHostTag()).thenReturn(hostTags.get(0));
|
||||
Mockito.when(template.getTemplateTag()).thenReturn(hostTags.get(0));
|
||||
Account account = Mockito.mock(Account.class);
|
||||
long delta = 256L;
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
resourceLimitManager.checkVmMemoryResourceLimit(account, true, serviceOffering, template, delta);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.memory, null, delta);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.memory, hostTags.get(0), delta);
|
||||
Assert.assertEquals(3, mockCheckedReservation.constructed().size());
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
|
|
@ -325,21 +287,15 @@ public class ResourceLimitManagerImplTest extends TestCase {
|
|||
|
||||
@Test
|
||||
public void testCheckVolumeResourceLimit() {
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
String checkTag = storageTags.get(0);
|
||||
DiskOffering diskOffering = Mockito.mock(DiskOffering.class);
|
||||
Mockito.when(diskOffering.getTags()).thenReturn(checkTag);
|
||||
Mockito.when(diskOffering.getTagsArray()).thenReturn(new String[]{checkTag});
|
||||
Account account = Mockito.mock(Account.class);
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
resourceLimitManager.checkVolumeResourceLimit(account, true, 100L, diskOffering);
|
||||
List<String> tags = new ArrayList<>();
|
||||
tags.add(null);
|
||||
tags.add(checkTag);
|
||||
for (String tag: tags) {
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.volume, tag);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, tag, 100L);
|
||||
}
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
resourceLimitManager.checkVolumeResourceLimit(account, true, 100L, diskOffering, reservations);
|
||||
Assert.assertEquals(2, reservations.size());
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
|
|
@ -934,13 +890,6 @@ public class ResourceLimitManagerImplTest extends TestCase {
|
|||
Mockito.anyList(), Mockito.eq(tag));
|
||||
}
|
||||
|
||||
private void mockCheckResourceLimitWithTag() throws ResourceAllocationException {
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(
|
||||
Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
|
||||
Mockito.doNothing().when(resourceLimitManager).checkResourceLimitWithTag(
|
||||
Mockito.any(Account.class), Mockito.any(Resource.ResourceType.class), Mockito.anyString(), Mockito.anyLong());
|
||||
}
|
||||
|
||||
private void mockIncrementResourceCountWithTag() {
|
||||
Mockito.doNothing().when(resourceLimitManager).incrementResourceCountWithTag(
|
||||
Mockito.anyLong(), Mockito.any(Resource.ResourceType.class), Mockito.anyString());
|
||||
|
|
@ -957,6 +906,7 @@ public class ResourceLimitManagerImplTest extends TestCase {
|
|||
|
||||
@Test
|
||||
public void testCheckVolumeResourceCount() throws ResourceAllocationException {
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
Account account = Mockito.mock(Account.class);
|
||||
String tag = "tag";
|
||||
long delta = 10L;
|
||||
|
|
@ -970,12 +920,11 @@ public class ResourceLimitManagerImplTest extends TestCase {
|
|||
|
||||
Mockito.doReturn(List.of(tag)).when(resourceLimitManager)
|
||||
.getResourceLimitStorageTagsForResourceCountOperation(Mockito.anyBoolean(), Mockito.any(DiskOffering.class));
|
||||
mockCheckResourceLimitWithTag();
|
||||
resourceLimitManager.checkVolumeResourceLimit(account, false, delta, Mockito.mock(DiskOffering.class));
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1)).checkResourceLimitWithTag(
|
||||
account, Resource.ResourceType.volume, tag);
|
||||
Mockito.verify(resourceLimitManager, Mockito.times(1))
|
||||
.checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, tag, 10L);
|
||||
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
resourceLimitManager.checkVolumeResourceLimit(account, false, delta, Mockito.mock(DiskOffering.class), reservations);
|
||||
Assert.assertEquals(2, reservations.size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import static org.mockito.ArgumentMatchers.eq;
|
|||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
|
@ -41,6 +40,7 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
import org.apache.cloudstack.api.command.user.volume.CheckAndRepairVolumeCmd;
|
||||
|
|
@ -83,6 +83,7 @@ import org.junit.runner.RunWith;
|
|||
import org.mockito.InOrder;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedConstruction;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
|
|
@ -91,7 +92,6 @@ import org.springframework.test.util.ReflectionTestUtils;
|
|||
|
||||
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.configuration.Resource.ResourceType;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
|
|
@ -545,7 +545,9 @@ public class VolumeApiServiceImplTest {
|
|||
@Test
|
||||
public void attachRootVolumePositive() throws NoSuchFieldException, IllegalAccessException {
|
||||
thrown.expect(NullPointerException.class);
|
||||
volumeApiServiceImpl.attachVolumeToVM(2L, 6L, 0L, false);
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
volumeApiServiceImpl.attachVolumeToVM(2L, 6L, 0L, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Negative test - attach data volume, to the vm on non-kvm hypervisor
|
||||
|
|
@ -564,7 +566,9 @@ public class VolumeApiServiceImplTest {
|
|||
DiskOfferingVO diskOffering = Mockito.mock(DiskOfferingVO.class);
|
||||
when(diskOffering.getEncrypt()).thenReturn(true);
|
||||
when(_diskOfferingDao.findById(anyLong())).thenReturn(diskOffering);
|
||||
volumeApiServiceImpl.attachVolumeToVM(4L, 10L, 1L, false);
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
volumeApiServiceImpl.attachVolumeToVM(4L, 10L, 1L, false);
|
||||
}
|
||||
}
|
||||
|
||||
// volume not Ready
|
||||
|
|
@ -649,9 +653,7 @@ public class VolumeApiServiceImplTest {
|
|||
* The resource limit check for primary storage should not be skipped for Volume in 'Uploaded' state.
|
||||
*/
|
||||
@Test
|
||||
public void testResourceLimitCheckForUploadedVolume() throws NoSuchFieldException, IllegalAccessException, ResourceAllocationException {
|
||||
doThrow(new ResourceAllocationException("primary storage resource limit check failed", Resource.ResourceType.primary_storage)).when(resourceLimitServiceMock)
|
||||
.checkResourceLimit(any(AccountVO.class), any(Resource.ResourceType.class), any(Long.class));
|
||||
public void testAttachVolumeToVMPerformsResourceReservation() throws NoSuchFieldException, IllegalAccessException, ResourceAllocationException {
|
||||
UserVmVO vm = Mockito.mock(UserVmVO.class);
|
||||
AccountVO acc = Mockito.mock(AccountVO.class);
|
||||
VolumeInfo volumeToAttach = Mockito.mock(VolumeInfo.class);
|
||||
|
|
@ -672,10 +674,10 @@ public class VolumeApiServiceImplTest {
|
|||
DataCenterVO zoneWithDisabledLocalStorage = Mockito.mock(DataCenterVO.class);
|
||||
when(_dcDao.findById(anyLong())).thenReturn(zoneWithDisabledLocalStorage);
|
||||
when(zoneWithDisabledLocalStorage.isLocalStorageEnabled()).thenReturn(true);
|
||||
try {
|
||||
doReturn(volumeVoMock).when(volumeApiServiceImpl).getVolumeAttachJobResult(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
volumeApiServiceImpl.attachVolumeToVM(2L, 9L, null, false);
|
||||
} catch (InvalidParameterValueException e) {
|
||||
Assert.assertEquals(e.getMessage(), ("primary storage resource limit check failed"));
|
||||
Assert.assertEquals(1, mockCheckedReservation.constructed().size());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2199,4 +2201,34 @@ public class VolumeApiServiceImplTest {
|
|||
Assert.fail();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequiredPrimaryStorageSizeForVolumeAttachTestTagsAreEmptyReturnsZero() {
|
||||
List<String> tags = new ArrayList<>();
|
||||
|
||||
Long result = volumeApiServiceImpl.getRequiredPrimaryStorageSizeForVolumeAttach(tags, volumeInfoMock);
|
||||
|
||||
Assert.assertEquals(0L, (long) result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequiredPrimaryStorageSizeForVolumeAttachTestVolumeIsReadyReturnsZero() {
|
||||
List<String> tags = List.of("tag1", "tag2");
|
||||
Mockito.doReturn(Volume.State.Ready).when(volumeInfoMock).getState();
|
||||
|
||||
Long result = volumeApiServiceImpl.getRequiredPrimaryStorageSizeForVolumeAttach(tags, volumeInfoMock);
|
||||
|
||||
Assert.assertEquals(0L, (long) result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequiredPrimaryStorageSizeForVolumeAttachTestTagsAreNotEmptyAndVolumeIsUploadedReturnsVolumeSize() {
|
||||
List<String> tags = List.of("tag1", "tag2");
|
||||
Mockito.doReturn(Volume.State.Uploaded).when(volumeInfoMock).getState();
|
||||
Mockito.doReturn(2L).when(volumeInfoMock).getSize();
|
||||
|
||||
Long result = volumeApiServiceImpl.getRequiredPrimaryStorageSizeForVolumeAttach(tags, volumeInfoMock);
|
||||
|
||||
Assert.assertEquals(2L, (long) result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import com.cloud.network.NetworkService;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
|
||||
|
|
@ -54,6 +55,7 @@ import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
|
|||
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.storage.template.VnfTemplateManager;
|
||||
|
|
@ -65,6 +67,7 @@ import org.junit.Test;
|
|||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedConstruction;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
|
@ -609,7 +612,6 @@ public class UserVmManagerImplTest {
|
|||
Mockito.doNothing().when(userVmManagerImpl).validateOldAndNewAccounts(Mockito.nullable(Account.class), Mockito.nullable(Account.class), Mockito.anyLong(), Mockito.nullable(String.class), Mockito.nullable(Long.class));
|
||||
Mockito.doNothing().when(userVmManagerImpl).validateIfVmHasNoRules(Mockito.any(), Mockito.anyLong());
|
||||
Mockito.doNothing().when(userVmManagerImpl).removeInstanceFromInstanceGroup(Mockito.anyLong());
|
||||
Mockito.doNothing().when(userVmManagerImpl).verifyResourceLimitsForAccountAndStorage(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyList(), Mockito.any());
|
||||
Mockito.doNothing().when(userVmManagerImpl).validateIfNewOwnerHasAccessToTemplate(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
||||
Mockito.doNothing().when(userVmManagerImpl).updateVmOwner(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
|
@ -1615,23 +1617,11 @@ public class UserVmManagerImplTest {
|
|||
Mockito.when(vol5.isDisplay()).thenReturn(true);
|
||||
|
||||
List<VolumeVO> volumes = List.of(vol1, undisplayedVolume, vol3, vol4, vol5);
|
||||
Long size = volumes.stream().filter(VolumeVO::isDisplay).mapToLong(VolumeVO::getSize).sum();
|
||||
try {
|
||||
userVmManagerImpl.checkVolumesLimits(account, volumes);
|
||||
Mockito.verify(resourceLimitMgr, Mockito.times(1))
|
||||
.checkResourceLimit(account, Resource.ResourceType.volume, 4);
|
||||
Mockito.verify(resourceLimitMgr, Mockito.times(1))
|
||||
.checkResourceLimit(account, Resource.ResourceType.primary_storage, size);
|
||||
Mockito.verify(resourceLimitMgr, Mockito.times(1))
|
||||
.checkResourceLimitWithTag(account, Resource.ResourceType.volume, "tag1", 2);
|
||||
Mockito.verify(resourceLimitMgr, Mockito.times(1))
|
||||
.checkResourceLimitWithTag(account, Resource.ResourceType.volume, "tag2", 3);
|
||||
Mockito.verify(resourceLimitMgr, Mockito.times(1))
|
||||
.checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, "tag1",
|
||||
vol1.getSize() + vol5.getSize());
|
||||
Mockito.verify(resourceLimitMgr, Mockito.times(1))
|
||||
.checkResourceLimitWithTag(account, Resource.ResourceType.primary_storage, "tag2",
|
||||
vol1.getSize() + vol3.getSize() + vol5.getSize());
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
userVmManagerImpl.checkVolumesLimits(account, volumes, reservations);
|
||||
Assert.assertEquals(8, reservations.size());
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
|
|
@ -1922,26 +1912,26 @@ public class UserVmManagerImplTest {
|
|||
|
||||
@Test
|
||||
public void verifyResourceLimitsForAccountAndStorageTestCountOnlyRunningVmsInResourceLimitationIsTrueDoesNotCallVmResourceLimitCheck() throws ResourceAllocationException {
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
LinkedList<VolumeVO> volumeVoList = new LinkedList<VolumeVO>();
|
||||
Mockito.doReturn(true).when(userVmManagerImpl).countOnlyRunningVmsInResourceLimitation();
|
||||
|
||||
userVmManagerImpl.verifyResourceLimitsForAccountAndStorage(accountMock, userVmVoMock, serviceOfferingVoMock, volumeVoList, virtualMachineTemplateMock);
|
||||
userVmManagerImpl.verifyResourceLimitsForAccountAndStorage(accountMock, userVmVoMock, serviceOfferingVoMock, volumeVoList, virtualMachineTemplateMock, reservations);
|
||||
|
||||
Mockito.verify(resourceLimitMgr, Mockito.never()).checkVmResourceLimit(Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any());
|
||||
Mockito.verify(resourceLimitMgr).checkResourceLimit(accountMock, Resource.ResourceType.volume, 0l);
|
||||
Mockito.verify(resourceLimitMgr).checkResourceLimit(accountMock, Resource.ResourceType.primary_storage, 0l);
|
||||
Mockito.verify(resourceLimitMgr, Mockito.never()).checkVmResourceLimit(Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Mockito.verify(resourceLimitMgr, Mockito.never()).checkVolumeResourceLimit(Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyResourceLimitsForAccountAndStorageTestCountOnlyRunningVmsInResourceLimitationIsFalseCallsVmResourceLimitCheck() throws ResourceAllocationException {
|
||||
List<Reserver> reservations = new ArrayList<>();
|
||||
LinkedList<VolumeVO> volumeVoList = new LinkedList<VolumeVO>();
|
||||
Mockito.doReturn(false).when(userVmManagerImpl).countOnlyRunningVmsInResourceLimitation();
|
||||
|
||||
userVmManagerImpl.verifyResourceLimitsForAccountAndStorage(accountMock, userVmVoMock, serviceOfferingVoMock, volumeVoList, virtualMachineTemplateMock);
|
||||
userVmManagerImpl.verifyResourceLimitsForAccountAndStorage(accountMock, userVmVoMock, serviceOfferingVoMock, volumeVoList, virtualMachineTemplateMock, reservations);
|
||||
|
||||
Mockito.verify(resourceLimitMgr).checkVmResourceLimit(Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any());
|
||||
Mockito.verify(resourceLimitMgr).checkResourceLimit(accountMock, Resource.ResourceType.volume, 0l);
|
||||
Mockito.verify(resourceLimitMgr).checkResourceLimit(accountMock, Resource.ResourceType.primary_storage, 0l);
|
||||
Mockito.verify(resourceLimitMgr).checkVmResourceLimit(Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Mockito.verify(userVmManagerImpl).checkVolumesLimits(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -2986,7 +2976,7 @@ public class UserVmManagerImplTest {
|
|||
configureDoNothingForMethodsThatWeDoNotWantToTest();
|
||||
|
||||
Mockito.doThrow(ResourceAllocationException.class).when(userVmManagerImpl).verifyResourceLimitsForAccountAndStorage(Mockito.any(), Mockito.any(),
|
||||
Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
||||
Assert.assertThrows(ResourceAllocationException.class, () -> userVmManagerImpl.moveVmToUser(assignVmCmdMock));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -357,13 +357,13 @@ public class VMSnapshotManagerTest {
|
|||
_vmSnapshotMgr.updateUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
|
||||
verify(_vmSnapshotMgr).changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVmMapDetails() {
|
||||
Map<String, String> result = _vmSnapshotMgr.getVmMapDetails(userVm);
|
||||
Map<String, String> result = _vmSnapshotMgr.getVmMapDetails(vmSnapshotVO);
|
||||
assert(result.containsKey(userVmDetailCpuNumber.getName()));
|
||||
assert(result.containsKey(userVmDetailMemory.getName()));
|
||||
assertEquals(userVmDetails.size(), result.size());
|
||||
|
|
@ -375,7 +375,7 @@ public class VMSnapshotManagerTest {
|
|||
public void testChangeUserVmServiceOffering() throws ConcurrentOperationException, ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException {
|
||||
when(_userVmManager.upgradeVirtualMachine(eq(TEST_VM_ID), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(true);
|
||||
_vmSnapshotMgr.changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
|
|
@ -383,7 +383,7 @@ public class VMSnapshotManagerTest {
|
|||
public void testChangeUserVmServiceOfferingFailOnUpgradeVMServiceOffering() throws ConcurrentOperationException, ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException {
|
||||
when(_userVmManager.upgradeVirtualMachine(eq(TEST_VM_ID), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(false);
|
||||
_vmSnapshotMgr.changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import javax.naming.ConfigurationException;
|
|||
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.resourcelimit.Reserver;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.configuration.Resource.ResourceType;
|
||||
|
|
@ -273,7 +274,7 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException {
|
||||
public void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -284,13 +285,13 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
|
||||
@Override
|
||||
public void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize,
|
||||
DiskOffering currentOffering, DiskOffering newOffering) throws ResourceAllocationException {
|
||||
DiskOffering currentOffering, DiskOffering newOffering, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size,
|
||||
DiskOffering diskOffering) {
|
||||
DiskOffering diskOffering, List<Reserver> reservations) {
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -334,7 +335,7 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template) throws ResourceAllocationException {
|
||||
public void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -351,19 +352,14 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
@Override
|
||||
public void checkVmResourceLimitsForServiceOfferingChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
|
||||
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering,
|
||||
VirtualMachineTemplate template) throws ResourceAllocationException {
|
||||
VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmResourceLimitsForTemplateChange(Account owner, Boolean display, ServiceOffering offering,
|
||||
VirtualMachineTemplate currentTemplate,
|
||||
VirtualMachineTemplate newTemplate) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmCpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu) throws ResourceAllocationException {
|
||||
VirtualMachineTemplate newTemplate, List<Reserver> reservations) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -377,11 +373,6 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkVmMemoryResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) throws ResourceAllocationException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) {
|
||||
|
||||
|
|
|
|||
|
|
@ -268,9 +268,6 @@ public class VolumeImportUnmanageManagerImplTest {
|
|||
doNothing().when(volumeImportUnmanageManager).checkIfVolumeIsEncrypted(volumeOnStorageTO);
|
||||
doNothing().when(volumeImportUnmanageManager).checkIfVolumeHasBackingFile(volumeOnStorageTO);
|
||||
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.volume);
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.primary_storage, virtualSize);
|
||||
|
||||
DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
|
||||
when(diskOffering.isCustomized()).thenReturn(true);
|
||||
doReturn(diskOffering).when(volumeImportUnmanageManager).getOrCreateDiskOffering(account, diskOfferingId, zoneId, isLocal);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import java.util.Map;
|
|||
import java.util.UUID;
|
||||
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import org.apache.cloudstack.api.ResponseGenerator;
|
||||
import org.apache.cloudstack.api.ResponseObject;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
|
|
@ -67,6 +68,7 @@ import org.junit.runner.RunWith;
|
|||
import org.mockito.BDDMockito;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedConstruction;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
|
@ -89,7 +91,6 @@ import com.cloud.agent.api.GetUnmanagedInstancesCommand;
|
|||
import com.cloud.agent.api.ImportConvertedInstanceAnswer;
|
||||
import com.cloud.agent.api.ImportConvertedInstanceCommand;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
|
|
@ -106,7 +107,6 @@ import com.cloud.exception.InsufficientServerCapacityException;
|
|||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.UnsupportedServiceException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
|
|
@ -282,7 +282,6 @@ public class UnmanagedVMsManagerImplTest {
|
|||
clusterVO.setHypervisorType(Hypervisor.HypervisorType.VMware.toString());
|
||||
when(clusterDao.findById(anyLong())).thenReturn(clusterVO);
|
||||
when(configurationDao.getValue(Mockito.anyString())).thenReturn(null);
|
||||
doNothing().when(resourceLimitService).checkResourceLimit(any(Account.class), any(Resource.ResourceType.class), anyLong());
|
||||
List<HostVO> hosts = new ArrayList<>();
|
||||
HostVO hostVO = Mockito.mock(HostVO.class);
|
||||
when(hostVO.isInMaintenanceStates()).thenReturn(false);
|
||||
|
|
@ -422,7 +421,8 @@ public class UnmanagedVMsManagerImplTest {
|
|||
when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance");
|
||||
when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null);
|
||||
when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true);
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class);
|
||||
MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -520,7 +520,8 @@ public class UnmanagedVMsManagerImplTest {
|
|||
CopyRemoteVolumeAnswer copyAnswer = Mockito.mock(CopyRemoteVolumeAnswer.class);
|
||||
when(copyAnswer.getResult()).thenReturn(true);
|
||||
when(agentManager.easySend(anyLong(), any(CopyRemoteVolumeCommand.class))).thenReturn(copyAnswer);
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class);
|
||||
MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
unmanagedVMsManager.importVm(cmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -707,7 +708,8 @@ public class UnmanagedVMsManagerImplTest {
|
|||
Mockito.lenient().when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ImportConvertedInstanceCommand.class))).thenReturn(convertImportedInstanceAnswer);
|
||||
}
|
||||
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class);
|
||||
MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
unmanagedVMsManager.importVm(importVmCmd);
|
||||
verify(vmwareGuru).getHypervisorVMOutOfBandAndCloneIfRequired(Mockito.eq(host), Mockito.eq(vmName), anyMap());
|
||||
verify(vmwareGuru).createVMTemplateOutOfBand(Mockito.eq(host), Mockito.eq(vmName), anyMap(), any(DataStoreTO.class), anyInt());
|
||||
|
|
@ -760,7 +762,8 @@ public class UnmanagedVMsManagerImplTest {
|
|||
when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true);
|
||||
StoragePoolHostVO storagePoolHost = Mockito.mock(StoragePoolHostVO.class);
|
||||
when(storagePoolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(storagePoolHost);
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
|
||||
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class);
|
||||
MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
unmanagedVMsManager.importVm(cmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -1107,40 +1110,4 @@ public class UnmanagedVMsManagerImplTest {
|
|||
|
||||
unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckUnmanagedDiskLimits() {
|
||||
Account owner = Mockito.mock(Account.class);
|
||||
UnmanagedInstanceTO.Disk disk = Mockito.mock(UnmanagedInstanceTO.Disk.class);
|
||||
Mockito.when(disk.getDiskId()).thenReturn("disk1");
|
||||
Mockito.when(disk.getCapacity()).thenReturn(100L);
|
||||
ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
|
||||
Mockito.when(serviceOffering.getDiskOfferingId()).thenReturn(1L);
|
||||
UnmanagedInstanceTO.Disk dataDisk = Mockito.mock(UnmanagedInstanceTO.Disk.class);
|
||||
Mockito.when(dataDisk.getDiskId()).thenReturn("disk2");
|
||||
Mockito.when(dataDisk.getCapacity()).thenReturn(1000L);
|
||||
Map<String, Long> dataDiskMap = new HashMap<>();
|
||||
dataDiskMap.put("disk2", 2L);
|
||||
DiskOfferingVO offering1 = Mockito.mock(DiskOfferingVO.class);
|
||||
Mockito.when(diskOfferingDao.findById(1L)).thenReturn(offering1);
|
||||
String tag1 = "tag1";
|
||||
Mockito.when(resourceLimitService.getResourceLimitStorageTags(offering1)).thenReturn(List.of(tag1));
|
||||
DiskOfferingVO offering2 = Mockito.mock(DiskOfferingVO.class);
|
||||
Mockito.when(diskOfferingDao.findById(2L)).thenReturn(offering2);
|
||||
String tag2 = "tag2";
|
||||
Mockito.when(resourceLimitService.getResourceLimitStorageTags(offering2)).thenReturn(List.of(tag2));
|
||||
try {
|
||||
Mockito.doNothing().when(resourceLimitService).checkResourceLimit(any(), any(), any());
|
||||
Mockito.doNothing().when(resourceLimitService).checkResourceLimitWithTag(any(), any(), any(), any());
|
||||
unmanagedVMsManager.checkUnmanagedDiskLimits(owner, disk, serviceOffering, List.of(dataDisk), dataDiskMap);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimit(owner, Resource.ResourceType.volume, 2);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimit(owner, Resource.ResourceType.primary_storage, 1100L);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimitWithTag(owner, Resource.ResourceType.volume, tag1,1);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimitWithTag(owner, Resource.ResourceType.volume, tag2,1);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimitWithTag(owner, Resource.ResourceType.primary_storage, tag1,100L);
|
||||
Mockito.verify(resourceLimitService, Mockito.times(1)).checkResourceLimitWithTag(owner, Resource.ResourceType.primary_storage, tag2,1000L);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail("Exception encountered: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue