diff --git a/engine/components-api/src/main/java/com/cloud/template/TemplateManager.java b/engine/components-api/src/main/java/com/cloud/template/TemplateManager.java index 28f41c677cb5..b5f5ebbcf89e 100644 --- a/engine/components-api/src/main/java/com/cloud/template/TemplateManager.java +++ b/engine/components-api/src/main/java/com/cloud/template/TemplateManager.java @@ -149,4 +149,6 @@ public interface TemplateManager { static Boolean getValidateUrlIsResolvableBeforeRegisteringTemplateValue() { return ValidateUrlIsResolvableBeforeRegisteringTemplate.value(); } + + void unlinkAllAndCleanupUserDataFromAccount(long accountId); } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java index 6785c3653290..448aa5101514 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDao.java @@ -103,4 +103,6 @@ public interface VMTemplateDao extends GenericDao, StateDao< List listIdsByTemplateTag(String tag); List listIdsByExtensionId(long extensionId); + + void unlinkUserdataFromTemplate(List userdataIds); } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java index 08b82cbb45bc..332f4b8ffcec 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -917,4 +917,20 @@ public boolean updateState( } return rows > 0; } + + @Override + public void unlinkUserdataFromTemplate(List userdataIds) { + if (CollectionUtils.isEmpty(userdataIds)) { + return; + } + SearchBuilder sb = createSearchBuilder(); + sb.and("userDataId", sb.entity().getUserDataId(), SearchCriteria.Op.IN); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("userDataId", userdataIds.toArray()); + VMTemplateVO vo = createForUpdate(); + vo.setUserDataId(null); + vo.setUserDataLinkPolicy(null); + update(vo, sc); + } } diff --git a/engine/schema/src/main/java/com/cloud/user/dao/UserDataDao.java b/engine/schema/src/main/java/com/cloud/user/dao/UserDataDao.java index 2733d8d2782f..c9e0c6c5d60f 100644 --- a/engine/schema/src/main/java/com/cloud/user/dao/UserDataDao.java +++ b/engine/schema/src/main/java/com/cloud/user/dao/UserDataDao.java @@ -16,6 +16,8 @@ // under the License. package com.cloud.user.dao; +import java.util.List; + import com.cloud.user.UserDataVO; import com.cloud.utils.db.GenericDao; @@ -25,6 +27,8 @@ public interface UserDataDao extends GenericDao { public UserDataVO findByName(long accountId, long domainId, String name); - int removeByAccountId(long accountId); + List listIdsByAccountId(long accountId); + + int removeAllIds(List ids); } diff --git a/engine/schema/src/main/java/com/cloud/user/dao/UserDataDaoImpl.java b/engine/schema/src/main/java/com/cloud/user/dao/UserDataDaoImpl.java index ded0cd172da3..65247577c0ad 100644 --- a/engine/schema/src/main/java/com/cloud/user/dao/UserDataDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/user/dao/UserDataDaoImpl.java @@ -16,10 +16,15 @@ // under the License. package com.cloud.user.dao; +import java.util.List; + import com.cloud.user.UserDataVO; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; + +import org.apache.commons.collections.CollectionUtils; import org.springframework.stereotype.Component; @Component @@ -65,9 +70,26 @@ public UserDataVO findByName(long accountId, long domainId, String name) { } @Override - public int removeByAccountId(long accountId) { - SearchCriteria sc = userdataSearch.create(); + public List listIdsByAccountId(long accountId) { + GenericSearchBuilder sb = createSearchBuilder(Long.class); + sb.selectFields(sb.entity().getId()); + sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ); + sb.done(); + SearchCriteria sc = sb.create(); sc.setParameters("accountId", accountId); + return customSearch(sc, null); + } + + @Override + public int removeAllIds(List ids) { + if (CollectionUtils.isEmpty(ids)) { + return 0; + } + SearchBuilder sb = createSearchBuilder(); + sb.and("idIn", sb.entity().getId(), SearchCriteria.Op.IN); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("idIn", ids.toArray()); return remove(sc); } } diff --git a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java index 5518a29955be..9de0701bb60b 100755 --- a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java @@ -193,6 +193,7 @@ import com.cloud.user.User; import com.cloud.user.UserData; import com.cloud.user.dao.AccountDao; +import com.cloud.user.dao.UserDataDao; import com.cloud.uservm.UserVm; import com.cloud.utils.DateUtil; import com.cloud.utils.EncryptionUtil; @@ -301,6 +302,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, private VMTemplateDetailsDao _tmpltDetailsDao; @Inject private HypervisorGuruManager _hvGuruMgr; + @Inject + UserDataDao userDataDao; private List _adapters; @@ -2495,4 +2498,14 @@ public VirtualMachineTemplate linkUserDataToTemplate(LinkUserDataToTemplateCmd c return _tmpltDao.findById(template.getId()); } + + @Override + public void unlinkAllAndCleanupUserDataFromAccount(long accountId) { + List userDataIds = userDataDao.listIdsByAccountId(accountId); + if (CollectionUtils.isEmpty(userDataIds)) { + return; + } + _tmpltDao.unlinkUserdataFromTemplate(userDataIds); + userDataDao.removeAllIds(userDataIds); + } } diff --git a/server/src/main/java/com/cloud/user/AccountManagerImpl.java b/server/src/main/java/com/cloud/user/AccountManagerImpl.java index a73a00d91526..9bc0210826c6 100644 --- a/server/src/main/java/com/cloud/user/AccountManagerImpl.java +++ b/server/src/main/java/com/cloud/user/AccountManagerImpl.java @@ -1201,7 +1201,7 @@ public int compare(NetworkVO network1, NetworkVO network2) { } // Delete registered UserData - userDataDao.removeByAccountId(accountId); + _tmpltMgr.unlinkAllAndCleanupUserDataFromAccount(accountId); // Delete Webhooks deleteWebhooksForAccount(accountId); diff --git a/server/src/test/java/com/cloud/template/TemplateManagerImplTest.java b/server/src/test/java/com/cloud/template/TemplateManagerImplTest.java index 819694a226b3..6cea7d5e9abc 100755 --- a/server/src/test/java/com/cloud/template/TemplateManagerImplTest.java +++ b/server/src/test/java/com/cloud/template/TemplateManagerImplTest.java @@ -63,6 +63,7 @@ import com.cloud.user.UserData; import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; +import com.cloud.user.dao.UserDataDao; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.exception.CloudRuntimeException; @@ -203,14 +204,19 @@ public class TemplateManagerImplTest { @Inject AccountManager _accountMgr; + @Inject VnfTemplateManager vnfTemplateManager; + @Inject SnapshotJoinDao snapshotJoinDao; @Inject HeuristicRuleHelper heuristicRuleHelperMock; + @Inject + UserDataDao userDataDao; + public class CustomThreadPoolExecutor extends ThreadPoolExecutor { AtomicInteger ai = new AtomicInteger(0); public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, @@ -978,11 +984,17 @@ public SecondaryStorageHeuristicDao secondaryStorageHeuristicDao() { public HeuristicRuleHelper heuristicRuleHelper() { return Mockito.mock(HeuristicRuleHelper.class); } + @Bean public SnapshotJoinDao snapshotJoinDao() { return Mockito.mock(SnapshotJoinDao.class); } + @Bean + public UserDataDao userDataDao() { + return Mockito.mock(UserDataDao.class); + } + public static class Library implements TypeFilter { @Override diff --git a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java index 3055e48247c4..7050d2f36871 100644 --- a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java +++ b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java @@ -200,7 +200,6 @@ public void deleteUserAccount() { sshkeyList.add(sshkey); Mockito.when(_sshKeyPairDao.listKeyPairs(Mockito.anyLong(), Mockito.anyLong())).thenReturn(sshkeyList); Mockito.when(_sshKeyPairDao.remove(Mockito.anyLong())).thenReturn(true); - Mockito.when(userDataDao.removeByAccountId(Mockito.anyLong())).thenReturn(222); Mockito.doNothing().when(accountManagerImpl).deleteWebhooksForAccount(Mockito.anyLong()); Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations((Account) any());