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);
Comment on lines +2151 to +2152
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logger.debug("Cannot delete Account {} (id={}), delete protection enabled for Instances: {}",
account.getAccountName(), accountId, vmUuids);
logger.debug("Cannot delete Account {}, delete protection enabled for Instances: {}",
account, vmUuids);

This logs the value of toString() method which includes these details.

public String reflectionToString() {
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "uuid", "accountName", "domainId");
}

}

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