Skip to content

Commit 57331ac

Browse files
authored
Skip removal of offerings if in use during domain removal (#11780)
This PR fixes #11502 - Prevent service offering update to specific domains if any instance for the offering are outside of those - Removal of offerings is skipped if it is in use by any Instance.
1 parent a29de0e commit 57331ac

File tree

6 files changed

+84
-5
lines changed

6 files changed

+84
-5
lines changed

engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,6 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long>, StateDao<Volume.S
162162
List<VolumeVO> searchRemovedByVms(List<Long> vmIds, Long batchSize);
163163

164164
VolumeVO findOneByIScsiName(String iScsiName);
165+
166+
int getVolumeCountByOfferingId(long diskOfferingId);
165167
}

engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
7777
protected GenericSearchBuilder<VolumeVO, SumCount> primaryStorageSearch2;
7878
protected GenericSearchBuilder<VolumeVO, SumCount> secondaryStorageSearch;
7979
private final SearchBuilder<VolumeVO> poolAndPathSearch;
80+
final GenericSearchBuilder<VolumeVO, Integer> CountByOfferingId;
8081

8182
@Inject
8283
ReservationDao reservationDao;
@@ -504,6 +505,11 @@ public VolumeDaoImpl() {
504505
poolAndPathSearch.and("poolId", poolAndPathSearch.entity().getPoolId(), Op.EQ);
505506
poolAndPathSearch.and("path", poolAndPathSearch.entity().getPath(), Op.EQ);
506507
poolAndPathSearch.done();
508+
509+
CountByOfferingId = createSearchBuilder(Integer.class);
510+
CountByOfferingId.select(null, Func.COUNT, CountByOfferingId.entity().getId());
511+
CountByOfferingId.and("diskOfferingId", CountByOfferingId.entity().getDiskOfferingId(), Op.EQ);
512+
CountByOfferingId.done();
507513
}
508514

509515
@Override
@@ -909,4 +915,12 @@ public VolumeVO findOneByIScsiName(String iScsiName) {
909915
sc.setParameters("iScsiName", iScsiName);
910916
return findOneIncludingRemovedBy(sc);
911917
}
918+
919+
@Override
920+
public int getVolumeCountByOfferingId(long diskOfferingId) {
921+
SearchCriteria<Integer> sc = CountByOfferingId.create();
922+
sc.setParameters("diskOfferingId", diskOfferingId);
923+
List<Integer> results = customSearch(sc, null);
924+
return results.get(0);
925+
}
912926
}

engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,7 @@ List<VMInstanceVO> searchRemovedByRemoveDate(final Date startDate, final Date en
187187

188188
Map<String, Long> getNameIdMapForVmIds(Collection<Long> ids);
189189

190+
int getVmCountByOfferingId(Long serviceOfferingId);
191+
192+
int getVmCountByOfferingNotInDomain(Long serviceOfferingId, List<Long> domainIds);
190193
}

engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
104104
protected SearchBuilder<VMInstanceVO> LastHostAndStatesSearch;
105105
protected SearchBuilder<VMInstanceVO> VmsNotInClusterUsingPool;
106106
protected SearchBuilder<VMInstanceVO> IdsPowerStateSelectSearch;
107+
GenericSearchBuilder<VMInstanceVO, Integer> CountByOfferingId;
108+
GenericSearchBuilder<VMInstanceVO, Integer> CountUserVmNotInDomain;
107109

108110
@Inject
109111
ResourceTagDao tagsDao;
@@ -344,6 +346,18 @@ protected void init() {
344346
IdsPowerStateSelectSearch.entity().getPowerStateUpdateCount(),
345347
IdsPowerStateSelectSearch.entity().getPowerStateUpdateTime());
346348
IdsPowerStateSelectSearch.done();
349+
350+
CountByOfferingId = createSearchBuilder(Integer.class);
351+
CountByOfferingId.select(null, Func.COUNT, CountByOfferingId.entity().getId());
352+
CountByOfferingId.and("serviceOfferingId", CountByOfferingId.entity().getServiceOfferingId(), Op.EQ);
353+
CountByOfferingId.done();
354+
355+
CountUserVmNotInDomain = createSearchBuilder(Integer.class);
356+
CountUserVmNotInDomain.select(null, Func.COUNT, CountUserVmNotInDomain.entity().getId());
357+
CountUserVmNotInDomain.and("serviceOfferingId", CountUserVmNotInDomain.entity().getServiceOfferingId(), Op.EQ);
358+
CountUserVmNotInDomain.and("domainIdsNotIn", CountUserVmNotInDomain.entity().getDomainId(), Op.NIN);
359+
CountUserVmNotInDomain.done();
360+
347361
}
348362

349363
@Override
@@ -1224,4 +1238,27 @@ public Map<String, Long> getNameIdMapForVmIds(Collection<Long> ids) {
12241238
return vms.stream()
12251239
.collect(Collectors.toMap(VMInstanceVO::getInstanceName, VMInstanceVO::getId));
12261240
}
1241+
1242+
@Override
1243+
public int getVmCountByOfferingId(Long serviceOfferingId) {
1244+
if (serviceOfferingId == null) {
1245+
return 0;
1246+
}
1247+
SearchCriteria<Integer> sc = CountByOfferingId.create();
1248+
sc.setParameters("serviceOfferingId", serviceOfferingId);
1249+
List<Integer> count = customSearch(sc, null);
1250+
return count.get(0);
1251+
}
1252+
1253+
@Override
1254+
public int getVmCountByOfferingNotInDomain(Long serviceOfferingId, List<Long> domainIds) {
1255+
if (serviceOfferingId == null || CollectionUtils.isEmpty(domainIds)) {
1256+
return 0;
1257+
}
1258+
SearchCriteria<Integer> sc = CountUserVmNotInDomain.create();
1259+
sc.setParameters("serviceOfferingId", serviceOfferingId);
1260+
sc.setParameters("domainIdsNotIn", domainIds.toArray());
1261+
List<Integer> count = customSearch(sc, null);
1262+
return count.get(0);
1263+
}
12271264
}

server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
import javax.inject.Inject;
5151
import javax.naming.ConfigurationException;
5252

53-
53+
import com.cloud.exception.UnsupportedServiceException;
5454
import com.cloud.network.as.AutoScaleManager;
5555
import com.cloud.user.AccountManagerImpl;
5656
import org.apache.cloudstack.acl.RoleType;
@@ -3722,6 +3722,12 @@ public ServiceOffering updateServiceOffering(final UpdateServiceOfferingCmd cmd)
37223722
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
37233723
Collections.sort(filteredDomainIds);
37243724

3725+
// avoid domain update of service offering if any instance is associated to it
3726+
int instanceCount = _vmInstanceDao.getVmCountByOfferingNotInDomain(offeringHandle.getId(), filteredDomainIds);
3727+
if (instanceCount > 0) {
3728+
throw new UnsupportedServiceException("There are Instances associated to this service offering outside of the specified domains.");
3729+
}
3730+
37253731
List<Long> filteredZoneIds = new ArrayList<>();
37263732
if (CollectionUtils.isNotEmpty(zoneIds)) {
37273733
filteredZoneIds.addAll(zoneIds);

server/src/main/java/com/cloud/user/DomainManagerImpl.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import com.cloud.api.query.vo.VpcOfferingJoinVO;
3535
import com.cloud.configuration.Resource;
3636
import com.cloud.domain.dao.DomainDetailsDao;
37+
import com.cloud.network.dao.NetworkDao;
38+
import com.cloud.network.vpc.dao.VpcDao;
3739
import com.cloud.network.vpc.dao.VpcOfferingDao;
3840
import com.cloud.network.vpc.dao.VpcOfferingDetailsDao;
3941
import com.cloud.offerings.dao.NetworkOfferingDao;
@@ -85,6 +87,7 @@
8587
import com.cloud.service.dao.ServiceOfferingDao;
8688
import com.cloud.service.dao.ServiceOfferingDetailsDao;
8789
import com.cloud.storage.dao.DiskOfferingDao;
90+
import com.cloud.storage.dao.VolumeDao;
8891
import com.cloud.user.dao.AccountDao;
8992
import com.cloud.utils.Pair;
9093
import com.cloud.utils.component.ManagerBase;
@@ -101,6 +104,8 @@
101104
import com.cloud.utils.net.NetUtils;
102105
import com.cloud.vm.ReservationContext;
103106
import com.cloud.vm.ReservationContextImpl;
107+
import com.cloud.vm.dao.VMInstanceDao;
108+
104109
import org.apache.commons.lang3.StringUtils;
105110

106111
@Component
@@ -141,6 +146,14 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom
141146
@Inject
142147
private ProjectDao _projectDao;
143148
@Inject
149+
private VMInstanceDao vmInstanceDao;
150+
@Inject
151+
private NetworkDao networkDao;
152+
@Inject
153+
private VolumeDao volumeDao;
154+
@Inject
155+
private VpcDao vpcDao;
156+
@Inject
144157
private ProjectManager _projectMgr;
145158
@Inject
146159
private RegionManager _regionMgr;
@@ -543,7 +556,8 @@ private void removeVpcOfferings(Long domainId, String domainIdString) {
543556
List<Long> vpcOfferingsDetailsToRemove = new ArrayList<>();
544557
List<VpcOfferingJoinVO> vpcOfferingsForThisDomain = vpcOfferingJoinDao.findByDomainId(domainId);
545558
for (VpcOfferingJoinVO vpcOffering : vpcOfferingsForThisDomain) {
546-
if (domainIdString.equals(vpcOffering.getDomainId())) {
559+
int vpcCount = vpcDao.getVpcCountByOfferingId(vpcOffering.getId());
560+
if (vpcCount == 0) {
547561
vpcOfferingDao.remove(vpcOffering.getId());
548562
} else {
549563
vpcOfferingsDetailsToRemove.add(vpcOffering.getId());
@@ -558,7 +572,8 @@ private void removeNetworkOfferings(Long domainId, String domainIdString) {
558572
List<Long> networkOfferingsDetailsToRemove = new ArrayList<>();
559573
List<NetworkOfferingJoinVO> networkOfferingsForThisDomain = networkOfferingJoinDao.findByDomainId(domainId, false);
560574
for (NetworkOfferingJoinVO networkOffering : networkOfferingsForThisDomain) {
561-
if (domainIdString.equals(networkOffering.getDomainId())) {
575+
int networkCount = networkDao.getNetworkCountByNetworkOffId(networkOffering.getId());
576+
if (networkCount == 0) {
562577
networkOfferingDao.remove(networkOffering.getId());
563578
} else {
564579
networkOfferingsDetailsToRemove.add(networkOffering.getId());
@@ -573,7 +588,8 @@ private void removeServiceOfferings(Long domainId, String domainIdString) {
573588
List<Long> serviceOfferingsDetailsToRemove = new ArrayList<>();
574589
List<ServiceOfferingJoinVO> serviceOfferingsForThisDomain = serviceOfferingJoinDao.findByDomainId(domainId);
575590
for (ServiceOfferingJoinVO serviceOffering : serviceOfferingsForThisDomain) {
576-
if (domainIdString.equals(serviceOffering.getDomainId())) {
591+
int vmCount = vmInstanceDao.getVmCountByOfferingId(serviceOffering.getId());
592+
if (vmCount == 0) {
577593
serviceOfferingDao.remove(serviceOffering.getId());
578594
} else {
579595
serviceOfferingsDetailsToRemove.add(serviceOffering.getId());
@@ -588,7 +604,8 @@ private void removeDiskOfferings(Long domainId, String domainIdString) {
588604
List<Long> diskOfferingsDetailsToRemove = new ArrayList<>();
589605
List<DiskOfferingJoinVO> diskOfferingsForThisDomain = diskOfferingJoinDao.findByDomainId(domainId);
590606
for (DiskOfferingJoinVO diskOffering : diskOfferingsForThisDomain) {
591-
if (domainIdString.equals(diskOffering.getDomainId())) {
607+
int volumeCount = volumeDao.getVolumeCountByOfferingId(diskOffering.getId());
608+
if (volumeCount == 0) {
592609
diskOfferingDao.remove(diskOffering.getId());
593610
} else {
594611
diskOfferingsDetailsToRemove.add(diskOffering.getId());

0 commit comments

Comments
 (0)