in server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java [3611:3791]
public ServiceOffering updateServiceOffering(final UpdateServiceOfferingCmd cmd) {
final String displayText = cmd.getDisplayText();
final Long id = cmd.getId();
final String name = cmd.getServiceOfferingName();
final Integer sortKey = cmd.getSortKey();
Long userId = CallContext.current().getCallingUserId();
final List<Long> domainIds = cmd.getDomainIds();
final List<Long> zoneIds = cmd.getZoneIds();
String storageTags = cmd.getStorageTags();
String hostTags = cmd.getHostTags();
ServiceOffering.State state = cmd.getState();
boolean purgeResources = cmd.isPurgeResources();
if (userId == null) {
userId = Long.valueOf(User.UID_SYSTEM);
}
// Verify input parameters
final ServiceOffering offeringHandle = _entityMgr.findById(ServiceOffering.class, id);
if (offeringHandle == null) {
throw new InvalidParameterValueException("unable to find service offering " + id);
}
List<Long> existingDomainIds = _serviceOfferingDetailsDao.findDomainIds(id);
Collections.sort(existingDomainIds);
List<Long> existingZoneIds = _serviceOfferingDetailsDao.findZoneIds(id);
Collections.sort(existingZoneIds);
String purgeResourceStr = _serviceOfferingDetailsDao.getDetail(id, ServiceOffering.PURGE_DB_ENTITIES_KEY);
boolean existingPurgeResources = false;
if (StringUtils.isNotBlank(purgeResourceStr)) {
existingPurgeResources = Boolean.parseBoolean(purgeResourceStr);
}
// check if valid domain
if (CollectionUtils.isNotEmpty(domainIds)) {
for (final Long domainId: domainIds) {
if (_domainDao.findById(domainId) == null) {
throw new InvalidParameterValueException("Please specify a valid domain id");
}
}
}
// check if valid zone
if (CollectionUtils.isNotEmpty(zoneIds)) {
for (Long zoneId : zoneIds) {
if (_zoneDao.findById(zoneId) == null)
throw new InvalidParameterValueException("Please specify a valid zone id");
}
}
final User user = _userDao.findById(userId);
if (user == null || user.getRemoved() != null) {
throw new InvalidParameterValueException("Unable to find active user by id " + userId);
}
final Account account = _accountDao.findById(user.getAccountId());
// Filter child domains when both parent and child domains are present
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
Collections.sort(filteredDomainIds);
List<Long> filteredZoneIds = new ArrayList<>();
if (CollectionUtils.isNotEmpty(zoneIds)) {
filteredZoneIds.addAll(zoneIds);
}
Collections.sort(filteredZoneIds);
if (account.getType() == Account.Type.DOMAIN_ADMIN) {
if (!filteredZoneIds.equals(existingZoneIds)) { // Domain-admins cannot update zone(s) for offerings
throw new InvalidParameterValueException(String.format("Unable to update zone(s) for service offering: %s by admin: %s as it is domain-admin", offeringHandle, user));
}
if (existingDomainIds.isEmpty()) {
throw new InvalidParameterValueException(String.format("Unable to update public service offering: %s by user: %s because it is domain-admin", offeringHandle, user));
} else {
if (filteredDomainIds.isEmpty()) {
throw new InvalidParameterValueException(String.format("Unable to update service offering: %s to a public offering by user: %s because it is domain-admin", offeringHandle, user));
}
}
if (!org.apache.commons.lang3.StringUtils.isAllBlank(hostTags, storageTags) && !ALLOW_DOMAIN_ADMINS_TO_CREATE_TAGGED_OFFERINGS.valueIn(account.getAccountId())) {
throw new InvalidParameterValueException(String.format("User [%s] is unable to update storage tags or host tags.", user));
}
List<Long> nonChildDomains = new ArrayList<>();
for (Long domainId : existingDomainIds) {
if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
if (name != null || displayText != null || sortKey != null) { // Domain-admins cannot update name, display text, sort key for offerings with domain which are not child domains for domain-admin
throw new InvalidParameterValueException(String.format("Unable to update service offering: %s as it has linked domain(s) which are not child domain for domain-admin: %s", offeringHandle, user));
}
nonChildDomains.add(domainId);
}
}
for (Long domainId : filteredDomainIds) {
if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) {
Domain domain = _entityMgr.findById(Domain.class, domainId);
throw new InvalidParameterValueException(String.format("Unable to update service offering: %s by domain-admin: %s with domain: %s which is not a child domain", offeringHandle, user, domain));
}
}
filteredDomainIds.addAll(nonChildDomains); // Final list must include domains which were not child domain for domain-admin but specified for this offering prior to update
} else if (account.getType() != Account.Type.ADMIN) {
throw new InvalidParameterValueException(String.format("Unable to update service offering: %s by id user: %s because it is not root-admin or domain-admin", offeringHandle, user));
}
final boolean updateNeeded = name != null || displayText != null || sortKey != null || storageTags != null || hostTags != null || state != null;
final boolean detailsUpdateNeeded = !filteredDomainIds.equals(existingDomainIds) ||
!filteredZoneIds.equals(existingZoneIds) || purgeResources != existingPurgeResources;
if (!updateNeeded && !detailsUpdateNeeded) {
return _serviceOfferingDao.findById(id);
}
ServiceOfferingVO offering = _serviceOfferingDao.createForUpdate(id);
if (name != null) {
offering.setName(name);
}
if (displayText != null) {
offering.setDisplayText(displayText);
}
if (sortKey != null) {
offering.setSortKey(sortKey);
}
if (state != null) {
offering.setState(state);
}
DiskOfferingVO diskOffering = _diskOfferingDao.findById(offeringHandle.getDiskOfferingId());
updateOfferingTagsIfIsNotNull(storageTags, diskOffering);
if (diskOffering.isComputeOnly() && state != null) {
diskOffering.setState(state == ServiceOffering.State.Active ? DiskOffering.State.Active : DiskOffering.State.Inactive);
}
_diskOfferingDao.update(diskOffering.getId(), diskOffering);
updateServiceOfferingHostTagsIfNotNull(hostTags, offering);
if (updateNeeded && !_serviceOfferingDao.update(id, offering)) {
return null;
}
List<ServiceOfferingDetailsVO> detailsVO = new ArrayList<>();
if(detailsUpdateNeeded) {
SearchBuilder<ServiceOfferingDetailsVO> sb = _serviceOfferingDetailsDao.createSearchBuilder();
sb.and("offeringId", sb.entity().getResourceId(), SearchCriteria.Op.EQ);
sb.and("detailName", sb.entity().getName(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<ServiceOfferingDetailsVO> sc = sb.create();
sc.setParameters("offeringId", String.valueOf(id));
if(!filteredDomainIds.equals(existingDomainIds)) {
sc.setParameters("detailName", ApiConstants.DOMAIN_ID);
_serviceOfferingDetailsDao.remove(sc);
for (Long domainId : filteredDomainIds) {
detailsVO.add(new ServiceOfferingDetailsVO(id, ApiConstants.DOMAIN_ID, String.valueOf(domainId), false));
}
}
if(!filteredZoneIds.equals(existingZoneIds)) {
sc.setParameters("detailName", ApiConstants.ZONE_ID);
_serviceOfferingDetailsDao.remove(sc);
for (Long zoneId : filteredZoneIds) {
detailsVO.add(new ServiceOfferingDetailsVO(id, ApiConstants.ZONE_ID, String.valueOf(zoneId), false));
}
}
if (purgeResources != existingPurgeResources) {
sc.setParameters("detailName", ServiceOffering.PURGE_DB_ENTITIES_KEY);
_serviceOfferingDetailsDao.remove(sc);
if (purgeResources) {
detailsVO.add(new ServiceOfferingDetailsVO(id, ServiceOffering.PURGE_DB_ENTITIES_KEY,
"true", false));
}
}
}
if (!detailsVO.isEmpty()) {
for (ServiceOfferingDetailsVO detailVO : detailsVO) {
_serviceOfferingDetailsDao.persist(detailVO);
}
}
offering = _serviceOfferingDao.findById(id);
CallContext.current().setEventDetails("Service offering id=" + offering.getId());
return offering;
}