public String updateConfiguration()

in server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java [696:913]


    public String updateConfiguration(final long userId, final String name, final String category, String value, final String scope, final Long resourceId) {
        final String validationMsg = validateConfigurationValue(name, value, scope);
        if (validationMsg != null) {
            logger.error("Invalid value [{}] for configuration [{}] due to [{}].", value, name, validationMsg);
            throw new InvalidParameterValueException(validationMsg);
        }

        // If scope of the parameter is given then it needs to be updated in the
        // corresponding details table,
        // if scope is mentioned as global or not mentioned then it is normal
        // global parameter updation
        if (scope != null && !scope.isEmpty() && !ConfigKey.Scope.Global.toString().equalsIgnoreCase(scope)) {
            boolean valueEncrypted = shouldEncryptValue(category);
            if (valueEncrypted) {
                value = DBEncryptionUtil.encrypt(value);
            }

            ApiCommandResourceType resourceType;
            ConfigKey.Scope scopeVal = ConfigKey.Scope.valueOf(scope);
            switch (scopeVal) {
            case Zone:
                final DataCenterVO zone = _zoneDao.findById(resourceId);
                if (zone == null) {
                    throw new InvalidParameterValueException("unable to find zone by id " + resourceId);
                }
                resourceType = ApiCommandResourceType.Zone;
                _dcDetailsDao.addDetail(resourceId, name, value, true);
                break;
            case Cluster:
                final ClusterVO cluster = _clusterDao.findById(resourceId);
                if (cluster == null) {
                    throw new InvalidParameterValueException("unable to find cluster by id " + resourceId);
                }
                resourceType = ApiCommandResourceType.Cluster;
                String newName = name;
                if (name.equalsIgnoreCase("cpu.overprovisioning.factor")) {
                    newName = "cpuOvercommitRatio";
                }
                if (name.equalsIgnoreCase("mem.overprovisioning.factor")) {
                    newName = "memoryOvercommitRatio";
                }
                ClusterDetailsVO clusterDetailsVO = _clusterDetailsDao.findDetail(resourceId, newName);
                if (clusterDetailsVO == null) {
                    clusterDetailsVO = new ClusterDetailsVO(resourceId, newName, value);
                    _clusterDetailsDao.persist(clusterDetailsVO);
                } else {
                    clusterDetailsVO.setValue(value);
                    _clusterDetailsDao.update(clusterDetailsVO.getId(), clusterDetailsVO);
                }
                break;

            case StoragePool:
                final StoragePoolVO pool = _storagePoolDao.findById(resourceId);
                if (pool == null) {
                    throw new InvalidParameterValueException("unable to find storage pool by id " + resourceId);
                }
                resourceType = ApiCommandResourceType.StoragePool;
                if(name.equals(CapacityManager.StorageOverprovisioningFactor.key())) {
                    if(!pool.getPoolType().supportsOverProvisioning() ) {
                        throw new InvalidParameterValueException(String.format("Unable to update storage pool %s. Overprovision not supported for %s", pool, pool.getPoolType()));
                    }
                }

                _storagePoolDetailsDao.addDetail(resourceId, name, value, true);
                if (pool.getPoolType() == Storage.StoragePoolType.DatastoreCluster) {
                    List<StoragePoolVO> childDataStores = _storagePoolDao.listChildStoragePoolsInDatastoreCluster(resourceId);
                    for (StoragePoolVO childDataStore: childDataStores) {
                        _storagePoolDetailsDao.addDetail(childDataStore.getId(), name, value, true);
                    }
                }

                break;

            case Account:
                final AccountVO account = _accountDao.findById(resourceId);
                if (account == null) {
                    throw new InvalidParameterValueException("unable to find account by id " + resourceId);
                }
                resourceType = ApiCommandResourceType.Account;
                AccountDetailVO accountDetailVO = _accountDetailsDao.findDetail(resourceId, name);
                if (accountDetailVO == null) {
                    accountDetailVO = new AccountDetailVO(resourceId, name, value);
                    _accountDetailsDao.persist(accountDetailVO);
                } else {
                    accountDetailVO.setValue(value);
                    _accountDetailsDao.update(accountDetailVO.getId(), accountDetailVO);
                }
                break;

            case ImageStore:
                final ImageStoreVO imgStore = _imageStoreDao.findById(resourceId);
                Preconditions.checkState(imgStore != null);
                resourceType = ApiCommandResourceType.ImageStore;
                _imageStoreDetailsDao.addDetail(resourceId, name, value, true);
                break;

            case Domain:
                final DomainVO domain = _domainDao.findById(resourceId);
                if (domain == null) {
                    throw new InvalidParameterValueException("unable to find domain by id " + resourceId);
                }
                resourceType = ApiCommandResourceType.Domain;
                DomainDetailVO domainDetailVO = _domainDetailsDao.findDetail(resourceId, name);
                if (domainDetailVO == null) {
                    domainDetailVO = new DomainDetailVO(resourceId, name, value);
                    _domainDetailsDao.persist(domainDetailVO);
                } else {
                    domainDetailVO.setValue(value);
                    _domainDetailsDao.update(domainDetailVO.getId(), domainDetailVO);
                }
                break;

            default:
                throw new InvalidParameterValueException("Scope provided is invalid");
            }

            CallContext.current().setEventResourceType(resourceType);
            CallContext.current().setEventResourceId(resourceId);
            CallContext.current().setEventDetails(String.format(" Name: %s, New Value: %s, Scope: %s", name, value, scope));

            _configDepot.invalidateConfigCache(name, scopeVal, resourceId);
            return valueEncrypted ? DBEncryptionUtil.decrypt(value) : value;
        }

        // Execute all updates in a single transaction
        final TransactionLegacy txn = TransactionLegacy.currentTxn();
        txn.start();

        String previousValue = _configDao.getValue(name);
        if (!_configDao.update(name, category, value)) {
            logger.error("Failed to update configuration option, name: " + name + ", value:" + value);
            throw new CloudRuntimeException("Failed to update configuration value. Please contact Cloud Support.");
        }
        _configDepot.invalidateConfigCache(name, ConfigKey.Scope.Global, null);

        PreparedStatement pstmt = null;
        if (Config.XenServerGuestNetwork.key().equalsIgnoreCase(name)) {
            final String sql = "update host_details set value=? where name=?";
            try {
                pstmt = txn.prepareAutoCloseStatement(sql);
                pstmt.setString(1, value);
                pstmt.setString(2, "guest.network.device");

                pstmt.executeUpdate();
            } catch (final Throwable e) {
                throw new CloudRuntimeException("Failed to update guest.network.device in host_details due to exception ", e);
            }
        } else if (Config.XenServerPrivateNetwork.key().equalsIgnoreCase(name)) {
            final String sql = "update host_details set value=? where name=?";
            try {
                pstmt = txn.prepareAutoCloseStatement(sql);
                pstmt.setString(1, value);
                pstmt.setString(2, "private.network.device");

                pstmt.executeUpdate();
            } catch (final Throwable e) {
                throw new CloudRuntimeException("Failed to update private.network.device in host_details due to exception ", e);
            }
        } else if (Config.XenServerPublicNetwork.key().equalsIgnoreCase(name)) {
            final String sql = "update host_details set value=? where name=?";
            try {
                pstmt = txn.prepareAutoCloseStatement(sql);
                pstmt.setString(1, value);
                pstmt.setString(2, "public.network.device");

                pstmt.executeUpdate();
            } catch (final Throwable e) {
                throw new CloudRuntimeException("Failed to update public.network.device in host_details due to exception ", e);
            }
        } else if (Config.XenServerStorageNetwork1.key().equalsIgnoreCase(name)) {
            final String sql = "update host_details set value=? where name=?";
            try {
                pstmt = txn.prepareAutoCloseStatement(sql);
                pstmt.setString(1, value);
                pstmt.setString(2, "storage.network.device1");

                pstmt.executeUpdate();
            } catch (final Throwable e) {
                throw new CloudRuntimeException("Failed to update storage.network.device1 in host_details due to exception ", e);
            }
        } else if (Config.XenServerStorageNetwork2.key().equals(name)) {
            final String sql = "update host_details set value=? where name=?";
            try {
                pstmt = txn.prepareAutoCloseStatement(sql);
                pstmt.setString(1, value);
                pstmt.setString(2, "storage.network.device2");

                pstmt.executeUpdate();
            } catch (final Throwable e) {
                throw new CloudRuntimeException("Failed to update storage.network.device2 in host_details due to exception ", e);
            }
        } else if (Config.SecStorageSecureCopyCert.key().equalsIgnoreCase(name)) {
            //FIXME - Ideally there should be a listener model to listen to global config changes and be able to take action gracefully.
            //Expire the download urls
            final String sqlTemplate = "update template_store_ref set download_url_created=?";
            final String sqlVolume = "update volume_store_ref set download_url_created=?";
            try {
                // Change for templates
                pstmt = txn.prepareAutoCloseStatement(sqlTemplate);
                pstmt.setDate(1, new Date(-1l));// Set the time before the epoch time.
                pstmt.executeUpdate();
                // Change for volumes
                pstmt = txn.prepareAutoCloseStatement(sqlVolume);
                pstmt.setDate(1, new Date(-1l));// Set the time before the epoch time.
                pstmt.executeUpdate();
                // Cleanup the download urls
                _storageManager.cleanupDownloadUrls();
            } catch (final Throwable e) {
                throw new CloudRuntimeException("Failed to clean up download URLs in template_store_ref or volume_store_ref due to exception ", e);
            }
        } else if (HypervisorGuru.HypervisorCustomDisplayName.key().equals(name)) {
            updateCustomDisplayNameOnHypervisorsList(previousValue, value);
        }

        txn.commit();
        messageBus.publish(_name, EventTypes.EVENT_CONFIGURATION_VALUE_EDIT, PublishScope.GLOBAL, name);
        return _configDao.getValue(name);
    }