Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,6 @@ List<VMInstanceVO> searchRemovedByRemoveDate(final Date startDate, final Date en
int getVmCountByOfferingNotInDomain(Long serviceOfferingId, List<Long> domainIds);

List<VMInstanceVO> listByIdsIncludingRemoved(List<Long> ids);

List<VMInstanceVO> listDeleteProtectedVmsByAccountId(long accountId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.apache.cloudstack.api.ApiConstants;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;

Expand Down Expand Up @@ -106,6 +107,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
protected SearchBuilder<VMInstanceVO> IdsPowerStateSelectSearch;
GenericSearchBuilder<VMInstanceVO, Integer> CountByOfferingId;
GenericSearchBuilder<VMInstanceVO, Integer> CountUserVmNotInDomain;
SearchBuilder<VMInstanceVO> DeleteProtectedVmSearch;

@Inject
ResourceTagDao tagsDao;
Expand Down Expand Up @@ -368,6 +370,12 @@ protected void init() {
CountUserVmNotInDomain.and("domainIdsNotIn", CountUserVmNotInDomain.entity().getDomainId(), Op.NIN);
CountUserVmNotInDomain.done();

DeleteProtectedVmSearch = createSearchBuilder();
DeleteProtectedVmSearch.selectFields(DeleteProtectedVmSearch.entity().getUuid());
DeleteProtectedVmSearch.and(ApiConstants.ACCOUNT_ID, DeleteProtectedVmSearch.entity().getAccountId(), Op.EQ);
DeleteProtectedVmSearch.and(ApiConstants.DELETE_PROTECTION, DeleteProtectedVmSearch.entity().isDeleteProtection(), Op.EQ);
DeleteProtectedVmSearch.and(ApiConstants.REMOVED, DeleteProtectedVmSearch.entity().getRemoved(), Op.NULL);
DeleteProtectedVmSearch.done();
}

@Override
Expand Down Expand Up @@ -1296,4 +1304,12 @@ public List<VMInstanceVO> listByIdsIncludingRemoved(List<Long> ids) {
sc.setParameters("ids", ids.toArray());
return listIncludingRemovedBy(sc);
}

@Override
public List<VMInstanceVO> listDeleteProtectedVmsByAccountId(long accountId) {
SearchCriteria<VMInstanceVO> sc = DeleteProtectedVmSearch.create();
sc.setParameters(ApiConstants.ACCOUNT_ID, accountId);
sc.setParameters(ApiConstants.DELETE_PROTECTION, true);
return listBy(sc);
}
}
19 changes: 19 additions & 0 deletions server/src/main/java/com/cloud/user/AccountManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -2097,6 +2097,7 @@ public boolean deleteUserAccount(long accountId) {
return true;
}

validateNoDeleteProtectedVms(account);
checkIfAccountManagesProjects(accountId);
verifyCallerPrivilegeForUserOrAccountOperations(account);

Expand Down Expand Up @@ -2138,6 +2139,24 @@ protected boolean isDeleteNeeded(AccountVO account, long accountId, Account call
return true;
}

private void validateNoDeleteProtectedVms(Account account) {
long accountId = account.getId();
List<VMInstanceVO> deleteProtectedVms = _vmDao.listDeleteProtectedVmsByAccountId(accountId);
if (deleteProtectedVms.isEmpty()) {
return;
}

if (logger.isDebugEnabled()) {
List<String> vmUuids = deleteProtectedVms.stream().map(VMInstanceVO::getUuid).collect(Collectors.toList());
logger.debug("Cannot delete Account {} (id={}), delete protection enabled for Instances: {}",
account.getAccountName(), accountId, vmUuids);
}

throw new InvalidParameterValueException(
String.format("Cannot delete Account '%s'. One or more Instances have delete protection enabled.",
account.getAccountName()));
}

@Override
@ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_ENABLE, eventDescription = "enabling account", async = true)
public AccountVO enableAccount(String accountName, Long domainId, Long accountId) {
Expand Down
Loading