public ServiceOffering updateServiceOffering()

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;
    }