server: clean network offerings for domain on remove (#7775)

diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
index f1e370d..74367a0 100644
--- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
@@ -969,7 +969,7 @@
     @Override
     public ListResponse<UserVmResponse> searchForUserVMs(ListVMsCmd cmd) {
         Pair<List<UserVmJoinVO>, Integer> result = searchForUserVMsInternal(cmd);
-        ListResponse<UserVmResponse> response = new ListResponse<UserVmResponse>();
+        ListResponse<UserVmResponse> response = new ListResponse<>();
         ResponseView respView = ResponseView.Restricted;
         Account caller = CallContext.current().getCallingAccount();
         if (_accountMgr.isRootAdmin(caller.getId())) {
@@ -1307,7 +1307,7 @@
             vmIds[i++] = v.getId();
         }
         List<UserVmJoinVO> vms = _userVmJoinDao.searchByIds(vmIds);
-        return new Pair<List<UserVmJoinVO>, Integer>(vms, count);
+        return new Pair<>(vms, count);
     }
 
     @Override
diff --git a/server/src/main/java/com/cloud/user/DomainManagerImpl.java b/server/src/main/java/com/cloud/user/DomainManagerImpl.java
index da796d2..ad05665 100644
--- a/server/src/main/java/com/cloud/user/DomainManagerImpl.java
+++ b/server/src/main/java/com/cloud/user/DomainManagerImpl.java
@@ -24,7 +24,15 @@
 
 import javax.inject.Inject;
 
+import com.cloud.api.query.dao.NetworkOfferingJoinDao;
+import com.cloud.api.query.dao.VpcOfferingJoinDao;
+import com.cloud.api.query.vo.NetworkOfferingJoinVO;
+import com.cloud.api.query.vo.VpcOfferingJoinVO;
 import com.cloud.domain.dao.DomainDetailsDao;
+import com.cloud.network.vpc.dao.VpcOfferingDao;
+import com.cloud.network.vpc.dao.VpcOfferingDetailsDao;
+import com.cloud.offerings.dao.NetworkOfferingDao;
+import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
 import org.apache.cloudstack.annotation.AnnotationService;
 import org.apache.cloudstack.annotation.dao.AnnotationDao;
 import org.apache.cloudstack.api.ApiConstants;
@@ -106,12 +114,24 @@
     @Inject
     private DiskOfferingDetailsDao diskOfferingDetailsDao;
     @Inject
+    private NetworkOfferingDao networkOfferingDao;
+    @Inject
+    private NetworkOfferingJoinDao networkOfferingJoinDao;
+    @Inject
+    private NetworkOfferingDetailsDao networkOfferingDetailsDao;
+    @Inject
     private ServiceOfferingJoinDao serviceOfferingJoinDao;
     @Inject
     private ServiceOfferingDao serviceOfferingDao;
     @Inject
     private ServiceOfferingDetailsDao serviceOfferingDetailsDao;
     @Inject
+    private VpcOfferingDao vpcOfferingDao;
+    @Inject
+    private VpcOfferingJoinDao vpcOfferingJoinDao;
+    @Inject
+    private VpcOfferingDetailsDao vpcOfferingDetailsDao;
+    @Inject
     private ProjectDao _projectDao;
     @Inject
     private ProjectManager _projectMgr;
@@ -483,18 +503,48 @@
         }
 
         String domainIdString = String.valueOf(domainId);
-        List<Long> diskOfferingsDetailsToRemove = new ArrayList<>();
-        List<Long> serviceOfferingsDetailsToRemove = new ArrayList<>();
 
-        // delete the service and disk offerings associated with this domain
-        List<DiskOfferingJoinVO> diskOfferingsForThisDomain = diskOfferingJoinDao.findByDomainId(domainId);
-        for (DiskOfferingJoinVO diskOffering : diskOfferingsForThisDomain) {
-            if (domainIdString.equals(diskOffering.getDomainId())) {
-                diskOfferingDao.remove(diskOffering.getId());
+        removeDiskOfferings(domainId, domainIdString);
+
+        removeServiceOfferings(domainId, domainIdString);
+
+        removeNetworkOfferings(domainId, domainIdString);
+
+        removeVpcOfferings(domainId, domainIdString);
+    }
+
+    private void removeVpcOfferings(Long domainId, String domainIdString) {
+        List<Long> vpcOfferingsDetailsToRemove = new ArrayList<>();
+        List<VpcOfferingJoinVO> vpcOfferingsForThisDomain = vpcOfferingJoinDao.findByDomainId(domainId);
+        for (VpcOfferingJoinVO vpcOffering : vpcOfferingsForThisDomain) {
+            if (domainIdString.equals(vpcOffering.getDomainId())) {
+                vpcOfferingDao.remove(vpcOffering.getId());
             } else {
-                diskOfferingsDetailsToRemove.add(diskOffering.getId());
+                vpcOfferingsDetailsToRemove.add(vpcOffering.getId());
             }
         }
+        for (final Long vpcOfferingId : vpcOfferingsDetailsToRemove) {
+            vpcOfferingDetailsDao.removeDetail(vpcOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
+        }
+    }
+
+    private void removeNetworkOfferings(Long domainId, String domainIdString) {
+        List<Long> networkOfferingsDetailsToRemove = new ArrayList<>();
+        List<NetworkOfferingJoinVO> networkOfferingsForThisDomain = networkOfferingJoinDao.findByDomainId(domainId, false);
+        for (NetworkOfferingJoinVO networkOffering : networkOfferingsForThisDomain) {
+            if (domainIdString.equals(networkOffering.getDomainId())) {
+                networkOfferingDao.remove(networkOffering.getId());
+            } else {
+                networkOfferingsDetailsToRemove.add(networkOffering.getId());
+            }
+        }
+        for (final Long networkOfferingId : networkOfferingsDetailsToRemove) {
+            networkOfferingDetailsDao.removeDetail(networkOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
+        }
+    }
+
+    private void removeServiceOfferings(Long domainId, String domainIdString) {
+        List<Long> serviceOfferingsDetailsToRemove = new ArrayList<>();
         List<ServiceOfferingJoinVO> serviceOfferingsForThisDomain = serviceOfferingJoinDao.findByDomainId(domainId);
         for (ServiceOfferingJoinVO serviceOffering : serviceOfferingsForThisDomain) {
             if (domainIdString.equals(serviceOffering.getDomainId())) {
@@ -503,14 +553,25 @@
                 serviceOfferingsDetailsToRemove.add(serviceOffering.getId());
             }
         }
+        for (final Long serviceOfferingId : serviceOfferingsDetailsToRemove) {
+            serviceOfferingDetailsDao.removeDetail(serviceOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
+        }
+    }
 
+    private void removeDiskOfferings(Long domainId, String domainIdString) {
+        List<Long> diskOfferingsDetailsToRemove = new ArrayList<>();
+        List<DiskOfferingJoinVO> diskOfferingsForThisDomain = diskOfferingJoinDao.findByDomainId(domainId);
+        for (DiskOfferingJoinVO diskOffering : diskOfferingsForThisDomain) {
+            if (domainIdString.equals(diskOffering.getDomainId())) {
+                diskOfferingDao.remove(diskOffering.getId());
+            } else {
+                diskOfferingsDetailsToRemove.add(diskOffering.getId());
+            }
+        }
         // Remove domain IDs for offerings which may be multi-domain
         for (final Long diskOfferingId : diskOfferingsDetailsToRemove) {
             diskOfferingDetailsDao.removeDetail(diskOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
         }
-        for (final Long serviceOfferingId : serviceOfferingsDetailsToRemove) {
-            serviceOfferingDetailsDao.removeDetail(serviceOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
-        }
     }
 
     protected boolean cleanupDomain(Long domainId, Long ownerId) throws ConcurrentOperationException, ResourceUnavailableException {
diff --git a/server/src/test/java/com/cloud/user/DomainManagerImplTest.java b/server/src/test/java/com/cloud/user/DomainManagerImplTest.java
index 0290c06..3b270f3 100644
--- a/server/src/test/java/com/cloud/user/DomainManagerImplTest.java
+++ b/server/src/test/java/com/cloud/user/DomainManagerImplTest.java
@@ -22,6 +22,8 @@
 import java.util.List;
 import java.util.UUID;
 
+import com.cloud.api.query.dao.NetworkOfferingJoinDao;
+import com.cloud.api.query.dao.VpcOfferingJoinDao;
 import com.cloud.configuration.ResourceLimit;
 import com.cloud.domain.dao.DomainDetailsDao;
 import com.cloud.utils.UuidUtils;
@@ -82,7 +84,11 @@
     @Mock
     DiskOfferingJoinDao _diskOfferingDao;
     @Mock
-    ServiceOfferingJoinDao _offeringsDao;
+    NetworkOfferingJoinDao networkOfferingJoinDao;
+    @Mock
+    ServiceOfferingJoinDao serviceOfferingJoinDao;
+    @Mock
+    VpcOfferingJoinDao vpcOfferingJoinDao;
     @Mock
     ProjectDao _projectDao;
     @Mock
@@ -142,6 +148,11 @@
         Mockito.when(_accountDao.findCleanupsForRemovedAccounts(DOMAIN_ID)).thenReturn(domainAccountsForCleanup);
         Mockito.when(_networkDomainDao.listNetworkIdsByDomain(DOMAIN_ID)).thenReturn(domainNetworkIds);
         Mockito.when(_dedicatedDao.listByDomainId(DOMAIN_ID)).thenReturn(domainDedicatedResources);
+
+        Mockito.when(_diskOfferingDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
+        Mockito.when(networkOfferingJoinDao.findByDomainId(Mockito.anyLong(), Mockito.anyBoolean())).thenReturn(Collections.emptyList());
+        Mockito.when(serviceOfferingJoinDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
+        Mockito.when(vpcOfferingJoinDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
     }
 
     @Test
@@ -266,8 +277,6 @@
         Mockito.when(_dedicatedDao.listByDomainId(Mockito.anyLong())).thenReturn(new ArrayList<DedicatedResourceVO>());
         Mockito.when(domainDaoMock.remove(Mockito.anyLong())).thenReturn(true);
         Mockito.when(_configMgr.releaseDomainSpecificVirtualRanges(Mockito.anyLong())).thenReturn(true);
-        Mockito.when(_diskOfferingDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
-        Mockito.when(_offeringsDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
 
         try {
             Assert.assertTrue(domainManager.deleteDomain(20l, false));
@@ -299,8 +308,6 @@
         Mockito.when(_resourceCountDao.removeEntriesByOwner(Mockito.anyLong(), Mockito.eq(ResourceOwnerType.Domain))).thenReturn(1l);
         Mockito.when(_resourceLimitDao.removeEntriesByOwner(Mockito.anyLong(), Mockito.eq(ResourceOwnerType.Domain))).thenReturn(1l);
         Mockito.when(_configMgr.releaseDomainSpecificVirtualRanges(Mockito.anyLong())).thenReturn(true);
-        Mockito.when(_diskOfferingDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
-        Mockito.when(_offeringsDao.findByDomainId(Mockito.anyLong())).thenReturn(Collections.emptyList());
 
         try {
             Assert.assertTrue(domainManager.deleteDomain(20l, true));