Skip to content

Commit 9c0c8da

Browse files
winterhazelDaan Hoogland
authored andcommitted
[22.0] Address limit checks for VM, CPU, memory, volume, and primary storage
1 parent f7f0e75 commit 9c0c8da

28 files changed

Lines changed: 845 additions & 737 deletions

File tree

api/src/main/java/com/cloud/projects/ProjectService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public interface ProjectService {
8282

8383
Project updateProject(long id, String name, String displayText, String newOwnerName, Long userId, Role newRole) throws ResourceAllocationException;
8484

85-
boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType);
85+
boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType) throws ResourceAllocationException;
8686

8787
boolean deleteAccountFromProject(long projectId, String accountName);
8888

@@ -100,6 +100,6 @@ public interface ProjectService {
100100

101101
Project findByProjectAccountIdIncludingRemoved(long projectAccountId);
102102

103-
boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole);
103+
boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole) throws ResourceAllocationException;
104104

105105
}

api/src/main/java/com/cloud/user/ResourceLimitService.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.cloud.offering.DiskOffering;
3131
import com.cloud.offering.ServiceOffering;
3232
import com.cloud.template.VirtualMachineTemplate;
33+
import org.apache.cloudstack.resourcelimit.Reserver;
3334

3435
public interface ResourceLimitService {
3536

@@ -252,12 +253,12 @@ public interface ResourceLimitService {
252253
List<String> getResourceLimitStorageTags(DiskOffering diskOffering);
253254
void updateTaggedResourceLimitsAndCountsForAccounts(List<AccountResponse> responses, String tag);
254255
void updateTaggedResourceLimitsAndCountsForDomains(List<DomainResponse> responses, String tag);
255-
void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException;
256+
void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException;
256257
List<String> getResourceLimitStorageTagsForResourceCountOperation(Boolean display, DiskOffering diskOffering);
257258
void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize,
258-
DiskOffering currentOffering, DiskOffering newOffering) throws ResourceAllocationException;
259+
DiskOffering currentOffering, DiskOffering newOffering, List<Reserver> reservations) throws ResourceAllocationException;
259260

260-
void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException;
261+
void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering, List<Reserver> reservations) throws ResourceAllocationException;
261262

262263
void incrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
263264
void decrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
@@ -274,20 +275,18 @@ void updateVolumeResourceCountForDiskOfferingChange(long accountId, Boolean disp
274275

275276
void incrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
276277
void decrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering);
277-
void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template) throws ResourceAllocationException;
278+
void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException;
278279
void incrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
279280
void decrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template);
280281

281282
void checkVmResourceLimitsForServiceOfferingChange(Account owner, Boolean display, Long currentCpu, Long newCpu,
282-
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template) throws ResourceAllocationException;
283+
Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template, List<Reserver> reservations) throws ResourceAllocationException;
283284

284285
void checkVmResourceLimitsForTemplateChange(Account owner, Boolean display, ServiceOffering offering,
285-
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate) throws ResourceAllocationException;
286+
VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate, List<Reserver> reservations) throws ResourceAllocationException;
286287

287-
void checkVmCpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu) throws ResourceAllocationException;
288288
void incrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu);
289289
void decrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu);
290-
void checkVmMemoryResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) throws ResourceAllocationException;
291290
void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
292291
void decrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
293292

api/src/main/java/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.List;
2020

21+
import com.cloud.exception.ResourceAllocationException;
2122
import org.apache.cloudstack.api.ApiArgValidator;
2223
import org.apache.cloudstack.api.ApiCommandResourceType;
2324
import org.apache.cloudstack.api.BaseCmd;
@@ -106,7 +107,7 @@ public ProjectAccount.Role getRoleType() {
106107
/////////////////////////////////////////////////////
107108

108109
@Override
109-
public void execute() {
110+
public void execute() throws ResourceAllocationException {
110111
if (accountName == null && email == null) {
111112
throw new InvalidParameterValueException("Either accountName or email is required");
112113
}

api/src/main/java/org/apache/cloudstack/api/command/user/account/AddUserToProjectCmd.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.apache.cloudstack.api.command.user.account;
1919

20+
import com.cloud.exception.ResourceAllocationException;
2021
import org.apache.cloudstack.acl.RoleType;
2122
import org.apache.cloudstack.api.APICommand;
2223
import org.apache.cloudstack.api.ApiArgValidator;
@@ -111,7 +112,7 @@ public String getEventDescription() {
111112
/////////////////////////////////////////////////////
112113

113114
@Override
114-
public void execute() {
115+
public void execute() throws ResourceAllocationException {
115116
validateInput();
116117
boolean result = _projectService.addUserToProject(getProjectId(), getUsername(), getEmail(), getProjectRoleId(), getRoleType());
117118
if (result) {

server/src/main/java/com/cloud/resourcelimit/Reserver.java renamed to api/src/main/java/org/apache/cloudstack/resourcelimit/Reserver.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,14 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
package com.cloud.resourcelimit;
18+
package org.apache.cloudstack.resourcelimit;
1919

20+
/**
21+
* Interface implemented by <code>CheckedReservation</code>.
22+
* </br></br>
23+
* This is defined in <code>cloud-api</code> to allow methods declared in modules that do not depend on <code>cloud-server</code>
24+
* to receive <code>CheckedReservations</code> as parameters.
25+
*/
2026
public interface Reserver extends AutoCloseable {
2127

2228
void close();

api/src/test/java/org/apache/cloudstack/api/command/test/AddAccountToProjectCmdTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package org.apache.cloudstack.api.command.test;
1818

19+
import com.cloud.exception.ResourceAllocationException;
1920
import junit.framework.Assert;
2021
import junit.framework.TestCase;
2122

@@ -149,6 +150,8 @@ public void testExecuteForNullAccountNameEmail() {
149150
addAccountToProjectCmd.execute();
150151
} catch (InvalidParameterValueException exception) {
151152
Assert.assertEquals("Either accountName or email is required", exception.getLocalizedMessage());
153+
} catch (ResourceAllocationException exception) {
154+
Assert.fail();
152155
}
153156

154157
}

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5222,9 +5222,20 @@ private void removeCustomOfferingDetails(long vmId) {
52225222

52235223
private void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering) {
52245224
Map<String, String> details = vmInstanceDetailsDao.listDetailsKeyPairs(vmId);
5225-
details.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
5226-
details.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
5227-
details.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
5225+
5226+
// We need to restore only the customizable parameters. If we save a parameter that is not customizable and attempt
5227+
// to restore a VM snapshot, com.cloud.vm.UserVmManagerImpl.validateCustomParameters will fail.
5228+
ServiceOffering unfilledOffering = _serviceOfferingDao.findByIdIncludingRemoved(serviceOffering.getId());
5229+
if (unfilledOffering.getCpu() == null) {
5230+
details.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
5231+
}
5232+
if (unfilledOffering.getSpeed() == null) {
5233+
details.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
5234+
}
5235+
if (unfilledOffering.getRamSize() == null) {
5236+
details.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
5237+
}
5238+
52285239
List<VMInstanceDetailVO> detailList = new ArrayList<>();
52295240
for (Map.Entry<String, String> entry: details.entrySet()) {
52305241
VMInstanceDetailVO detailVO = new VMInstanceDetailVO(vmId, entry.getKey(), entry.getValue(), true);

engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3123,9 +3123,6 @@ public Network doInTransaction(final TransactionStatus status) {
31233123
CallContext.current().setEventDetails("Network Id: " + network.getId());
31243124
CallContext.current().putContextParameter(Network.class, network.getUuid());
31253125
return network;
3126-
} catch (Exception e) {
3127-
logger.error(e);
3128-
throw new RuntimeException(e);
31293126
}
31303127
}
31313128

engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
import com.cloud.deploy.DeploymentClusterPlanner;
4242
import com.cloud.exception.ResourceAllocationException;
43+
import com.cloud.resourcelimit.ReservationHelper;
4344
import com.cloud.storage.DiskOfferingVO;
4445
import com.cloud.storage.VMTemplateVO;
4546
import com.cloud.storage.dao.VMTemplateDao;
@@ -82,6 +83,7 @@
8283
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
8384
import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO;
8485
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
86+
import org.apache.cloudstack.resourcelimit.Reserver;
8587
import org.apache.cloudstack.secret.PassphraseVO;
8688
import org.apache.cloudstack.secret.dao.PassphraseDao;
8789
import org.apache.cloudstack.snapshot.SnapshotHelper;
@@ -1942,24 +1944,32 @@ protected void updateVolumeSize(DataStore store, VolumeVO vol) throws ResourceAl
19421944
template == null ? null : template.getSize(),
19431945
vol.getPassphraseId() != null);
19441946

1945-
if (newSize != vol.getSize()) {
1946-
DiskOfferingVO diskOffering = diskOfferingDao.findByIdIncludingRemoved(vol.getDiskOfferingId());
1947+
if (newSize == vol.getSize()) {
1948+
return;
1949+
}
1950+
1951+
DiskOfferingVO diskOffering = diskOfferingDao.findByIdIncludingRemoved(vol.getDiskOfferingId());
1952+
1953+
List<Reserver> reservations = new ArrayList<>();
1954+
try {
19471955
VMInstanceVO vm = vol.getInstanceId() != null ? vmInstanceDao.findById(vol.getInstanceId()) : null;
19481956
if (vm == null || vm.getType() == VirtualMachine.Type.User) {
19491957
// Update resource count for user vm volumes when volume is attached
19501958
if (newSize > vol.getSize()) {
19511959
_resourceLimitMgr.checkPrimaryStorageResourceLimit(_accountMgr.getActiveAccountById(vol.getAccountId()),
1952-
vol.isDisplay(), newSize - vol.getSize(), diskOffering);
1960+
vol.isDisplay(), newSize - vol.getSize(), diskOffering, reservations);
19531961
_resourceLimitMgr.incrementVolumePrimaryStorageResourceCount(vol.getAccountId(), vol.isDisplay(),
19541962
newSize - vol.getSize(), diskOffering);
19551963
} else {
19561964
_resourceLimitMgr.decrementVolumePrimaryStorageResourceCount(vol.getAccountId(), vol.isDisplay(),
19571965
vol.getSize() - newSize, diskOffering);
19581966
}
19591967
}
1960-
vol.setSize(newSize);
1961-
_volsDao.persist(vol);
1968+
} finally {
1969+
ReservationHelper.closeAll(reservations);
19621970
}
1971+
vol.setSize(newSize);
1972+
_volsDao.persist(vol);
19631973
}
19641974

19651975
@Override

server/src/main/java/com/cloud/projects/ProjectManagerImpl.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ public ProjectVO findByProjectAccountIdIncludingRemoved(long projectAccountId) {
544544

545545
@Override
546546
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_USER_ADD, eventDescription = "adding user to project", async = true)
547-
public boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole) {
547+
public boolean addUserToProject(Long projectId, String username, String email, Long projectRoleId, Role projectRole) throws ResourceAllocationException {
548548
Account caller = CallContext.current().getCallingAccount();
549549

550550
Project project = getProject(projectId);
@@ -614,8 +614,6 @@ public boolean addUserToProject(Long projectId, String username, String email, L
614614
logger.warn("Failed to add user to project: {}", project);
615615
return false;
616616
}
617-
} catch (ResourceAllocationException e) {
618-
throw new RuntimeException(e);
619617
}
620618
}
621619
}
@@ -814,7 +812,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Resour
814812

815813
@Override
816814
@ActionEvent(eventType = EventTypes.EVENT_PROJECT_ACCOUNT_ADD, eventDescription = "adding account to project", async = true)
817-
public boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType) {
815+
public boolean addAccountToProject(long projectId, String accountName, String email, Long projectRoleId, Role projectRoleType) throws ResourceAllocationException {
818816
Account caller = CallContext.current().getCallingAccount();
819817

820818
//check that the project exists
@@ -892,8 +890,6 @@ public boolean addAccountToProject(long projectId, String accountName, String em
892890
logger.warn("Failed to add account {} to project {}", accountName, project);
893891
return false;
894892
}
895-
} catch (ResourceAllocationException e) {
896-
throw new RuntimeException(e);
897893
}
898894
}
899895
}

0 commit comments

Comments
 (0)