You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by da...@apache.org on 2021/09/29 08:29:39 UTC

[cloudstack] branch main updated: Enable account settings to be visible under domain settings (#4215)

This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/main by this push:
     new dcc02e0  Enable account settings to be visible under domain settings (#4215)
dcc02e0 is described below

commit dcc02e0fbb8bfdc264cde06024f00fa724da8885
Author: Rakesh <ra...@gmail.com>
AuthorDate: Wed Sep 29 10:29:20 2021 +0200

    Enable account settings to be visible under domain settings (#4215)
    
    * Enable account settings to be visible under domain settings
    
    All the account settings can't be configured under domain
    level settings right now.
    By default, if account setting is not configured then
    its value will be taken from global setting.
    Add a global setting "enable.account.settings.for.domain"
    so that if its enabled then all the account level settings
    will be visible under domain levelsettings also.
    If account level setting is configured then that value will
    be considered else it will take domain scope value. If
    domain scope value is not configured then it will pick
    it up from global setting.
    
    If domain level setting is not configured then by default
    the value will be taken from global setting
    Add another global setting "enable.domain.settings.for.child.domain"
    so that when its true, if a value for domain setting is not
    configured then its parent domain value is considered until
    it reaches ROOT domain. If no value is configured till ROOT
    domain then global setting value will be taken.
    
    Also display all the settings configured under the domain level
    in list domains api response
    
    * rename variables
    
    Co-authored-by: Rakesh Venkatesh <ra...@apache.org>
---
 .../org/apache/cloudstack/api/ApiConstants.java    |   1 +
 .../cloudstack/api/response/DomainResponse.java    |   9 +
 .../com/cloud/domain/dao/DomainDetailsDaoImpl.java |  28 +-
 .../java/com/cloud/user/AccountDetailsDaoImpl.java |  52 ++-
 .../cloudstack/framework/config/ConfigKey.java     |  13 +
 .../framework/config/impl/ConfigDepotImpl.java     |  10 +
 server/src/main/java/com/cloud/api/ApiDBUtils.java | 152 +++---
 .../com/cloud/api/query/dao/DomainJoinDaoImpl.java |   1 +
 .../configuration/ConfigurationManagerImpl.java    |  13 +-
 .../com/cloud/server/ManagementServerImpl.java     |  16 +-
 .../test_enable_account_settings_for_domain.py     | 514 +++++++++++++++++++++
 11 files changed, 731 insertions(+), 78 deletions(-)

diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 0fff4ef..cb4e647 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -137,6 +137,7 @@ public class ApiConstants {
     public static final String IP6_DNS1 = "ip6dns1";
     public static final String IP6_DNS2 = "ip6dns2";
     public static final String DOMAIN = "domain";
+    public static final String DOMAIN_DETAILS = "domaindetails";
     public static final String DOMAIN_PATH = "domainpath";
     public static final String DOMAIN_ID = "domainid";
     public static final String DOMAIN__ID = "domainId";
diff --git a/api/src/main/java/org/apache/cloudstack/api/response/DomainResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/DomainResponse.java
index 6d56552..e4e409a 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/DomainResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/DomainResponse.java
@@ -26,6 +26,7 @@ import com.cloud.domain.Domain;
 import com.cloud.serializer.Param;
 
 import java.util.Date;
+import java.util.Map;
 
 @EntityReference(value = Domain.class)
 public class DomainResponse extends BaseResponseWithAnnotations implements ResourceLimitAndCountResponse, SetResourceIconResponse {
@@ -179,6 +180,10 @@ public class DomainResponse extends BaseResponseWithAnnotations implements Resou
     @Param(description = "Base64 string representation of the resource icon", since = "4.16.0.0")
     ResourceIconResponse icon;
 
+    @SerializedName(ApiConstants.DOMAIN_DETAILS)
+    @Param(description = "details for the domain")
+    private Map<String, String> details;
+
     public String getId() {
         return this.id;
     }
@@ -438,4 +443,8 @@ public class DomainResponse extends BaseResponseWithAnnotations implements Resou
     public void setResourceIconResponse(ResourceIconResponse icon) {
         this.icon = icon;
     }
+
+    public void setDetails(Map<String, String> details) {
+        this.details = details;
+    }
 }
diff --git a/engine/schema/src/main/java/com/cloud/domain/dao/DomainDetailsDaoImpl.java b/engine/schema/src/main/java/com/cloud/domain/dao/DomainDetailsDaoImpl.java
index ad7f704..dad3fe9 100644
--- a/engine/schema/src/main/java/com/cloud/domain/dao/DomainDetailsDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/domain/dao/DomainDetailsDaoImpl.java
@@ -20,7 +20,10 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.inject.Inject;
+
 import com.cloud.domain.DomainDetailVO;
+import com.cloud.domain.DomainVO;
 import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.QueryBuilder;
 import com.cloud.utils.db.SearchBuilder;
@@ -30,10 +33,16 @@ import com.cloud.utils.db.TransactionLegacy;
 import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.ConfigKey.Scope;
 import org.apache.cloudstack.framework.config.ScopedConfigStorage;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 
 public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> implements DomainDetailsDao, ScopedConfigStorage {
     protected final SearchBuilder<DomainDetailVO> domainSearch;
 
+    @Inject
+    protected DomainDao _domainDao;
+    @Inject
+    private ConfigurationDao _configDao;
+
     protected DomainDetailsDaoImpl() {
         domainSearch = createSearchBuilder();
         domainSearch.and("domainId", domainSearch.entity().getDomainId(), Op.EQ);
@@ -98,7 +107,24 @@ public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> i
 
     @Override
     public String getConfigValue(long id, ConfigKey<?> key) {
-        DomainDetailVO vo = findDetail(id, key.key());
+        DomainDetailVO vo = null;
+        String enableDomainSettingsForChildDomain = _configDao.getValue("enable.domain.settings.for.child.domain");
+        if (!Boolean.parseBoolean(enableDomainSettingsForChildDomain)) {
+            vo = findDetail(id, key.key());
+            return vo == null ? null : vo.getValue();
+        }
+        DomainVO domain = _domainDao.findById(id);
+        // if value is not configured in domain then check its parent domain till ROOT
+        while (domain != null) {
+            vo = findDetail(domain.getId(), key.key());
+            if (vo != null) {
+                break;
+            } else if (domain.getParent() != null) {
+                domain = _domainDao.findById(domain.getParent());
+            } else {
+                break;
+            }
+        }
         return vo == null ? null : vo.getValue();
     }
 }
diff --git a/engine/schema/src/main/java/com/cloud/user/AccountDetailsDaoImpl.java b/engine/schema/src/main/java/com/cloud/user/AccountDetailsDaoImpl.java
index c8675d8..5451192 100644
--- a/engine/schema/src/main/java/com/cloud/user/AccountDetailsDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/user/AccountDetailsDaoImpl.java
@@ -19,22 +19,40 @@ package com.cloud.user;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
+import javax.inject.Inject;
 
 import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.ConfigKey.Scope;
 import org.apache.cloudstack.framework.config.ScopedConfigStorage;
 
+import com.cloud.domain.DomainDetailVO;
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDetailsDao;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.user.dao.AccountDao;
+
 import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.QueryBuilder;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.SearchCriteria.Op;
 import com.cloud.utils.db.TransactionLegacy;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 
 public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long> implements AccountDetailsDao, ScopedConfigStorage {
     protected final SearchBuilder<AccountDetailVO> accountSearch;
 
+    @Inject
+    protected AccountDao _accountDao;
+    @Inject
+    protected DomainDao _domainDao;
+    @Inject
+    protected DomainDetailsDao _domainDetailsDao;
+    @Inject
+    private ConfigurationDao _configDao;
+
     protected AccountDetailsDaoImpl() {
         accountSearch = createSearchBuilder();
         accountSearch.and("accountId", accountSearch.entity().getAccountId(), Op.EQ);
@@ -99,7 +117,39 @@ public class AccountDetailsDaoImpl extends GenericDaoBase<AccountDetailVO, Long>
 
     @Override
     public String getConfigValue(long id, ConfigKey<?> key) {
+        // check if account level setting is configured
         AccountDetailVO vo = findDetail(id, key.key());
-        return vo == null ? null : vo.getValue();
+        String value = vo == null ? null : vo.getValue();
+        if (value != null) {
+            return value;
+        }
+
+        // if account level setting is not configured then check if
+        // we can take value from domain
+        String enableAccountSettingsForDomain = _configDao.getValue("enable.account.settings.for.domain");
+        if (! Boolean.parseBoolean(enableAccountSettingsForDomain)) {
+            return null;
+        }
+
+        // check if we can traverse till ROOT domain to get the value
+        String enableDomainSettingsForChildDomain = _configDao.getValue("enable.domain.settings.for.child.domain");
+        if (Boolean.parseBoolean(enableDomainSettingsForChildDomain)) {
+            Optional<AccountVO> account = Optional.ofNullable(_accountDao.findById(id));
+            if (account.isPresent()) {
+                DomainVO domain = _domainDao.findById(account.get().getDomainId());
+                while (domain != null) {
+                    DomainDetailVO domainVO = _domainDetailsDao.findDetail(domain.getId(), key.key());
+                    if (domainVO != null) {
+                        value = domainVO.getValue();
+                        break;
+                    } else if (domain.getParent() != null) {
+                        domain = _domainDao.findById(domain.getParent());
+                    } else {
+                        break;
+                    }
+                }
+            }
+        }
+        return value;
     }
 }
diff --git a/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java b/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java
index 2ace24d..d22fe1f 100644
--- a/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java
+++ b/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java
@@ -160,6 +160,19 @@ public class ConfigKey<T> {
         }
     }
 
+    public T valueInDomain(Long domainId) {
+        if (domainId == null) {
+            return value();
+        }
+
+        String value = s_depot != null ? s_depot.getDomainScope(this).getConfigValue(domainId, this) : null;
+        if (value == null) {
+            return value();
+        } else {
+            return valueOf(value);
+        }
+    }
+
     @SuppressWarnings("unchecked")
     protected T valueOf(String value) {
         Number multiplier = 1;
diff --git a/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java b/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java
index ddc06b6..1cb93dc 100644
--- a/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java
+++ b/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java
@@ -186,6 +186,16 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
         throw new CloudRuntimeException("Unable to find config storage for this scope: " + config.scope() + " for " + config.key());
     }
 
+    public ScopedConfigStorage getDomainScope(ConfigKey<?> config) {
+        for (ScopedConfigStorage storage : _scopedStorages) {
+            if (storage.getScope() == ConfigKey.Scope.Domain) {
+                return storage;
+            }
+        }
+
+        throw new CloudRuntimeException("Unable to find config storage for this scope: " + ConfigKey.Scope.Domain + " for " + config.key());
+    }
+
     public List<ScopedConfigStorage> getScopedStorages() {
         return _scopedStorages;
     }
diff --git a/server/src/main/java/com/cloud/api/ApiDBUtils.java b/server/src/main/java/com/cloud/api/ApiDBUtils.java
index 3694244..28bafe2 100644
--- a/server/src/main/java/com/cloud/api/ApiDBUtils.java
+++ b/server/src/main/java/com/cloud/api/ApiDBUtils.java
@@ -16,77 +16,6 @@
 // under the License.
 package com.cloud.api;
 
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-
-import com.cloud.resource.icon.ResourceIconVO;
-import com.cloud.resource.icon.dao.ResourceIconDao;
-import com.cloud.server.ResourceIcon;
-import org.apache.cloudstack.acl.Role;
-import org.apache.cloudstack.acl.RoleService;
-import org.apache.cloudstack.affinity.AffinityGroup;
-import org.apache.cloudstack.affinity.AffinityGroupResponse;
-import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
-import org.apache.cloudstack.api.ApiCommandJobType;
-import org.apache.cloudstack.api.ApiConstants.DomainDetails;
-import org.apache.cloudstack.api.ApiConstants.HostDetails;
-import org.apache.cloudstack.api.ApiConstants.VMDetails;
-import org.apache.cloudstack.api.ResponseObject.ResponseView;
-import org.apache.cloudstack.api.response.AccountResponse;
-import org.apache.cloudstack.api.response.AsyncJobResponse;
-import org.apache.cloudstack.api.response.BackupOfferingResponse;
-import org.apache.cloudstack.api.response.BackupResponse;
-import org.apache.cloudstack.api.response.BackupScheduleResponse;
-import org.apache.cloudstack.api.response.DiskOfferingResponse;
-import org.apache.cloudstack.api.response.DomainResponse;
-import org.apache.cloudstack.api.response.DomainRouterResponse;
-import org.apache.cloudstack.api.response.EventResponse;
-import org.apache.cloudstack.api.response.HostForMigrationResponse;
-import org.apache.cloudstack.api.response.HostResponse;
-import org.apache.cloudstack.api.response.HostTagResponse;
-import org.apache.cloudstack.api.response.ImageStoreResponse;
-import org.apache.cloudstack.api.response.InstanceGroupResponse;
-import org.apache.cloudstack.api.response.NetworkOfferingResponse;
-import org.apache.cloudstack.api.response.ProjectAccountResponse;
-import org.apache.cloudstack.api.response.ProjectInvitationResponse;
-import org.apache.cloudstack.api.response.ProjectResponse;
-import org.apache.cloudstack.api.response.ResourceIconResponse;
-import org.apache.cloudstack.api.response.ResourceTagResponse;
-import org.apache.cloudstack.api.response.SecurityGroupResponse;
-import org.apache.cloudstack.api.response.ServiceOfferingResponse;
-import org.apache.cloudstack.api.response.StoragePoolResponse;
-import org.apache.cloudstack.api.response.StorageTagResponse;
-import org.apache.cloudstack.api.response.TemplateResponse;
-import org.apache.cloudstack.api.response.UserResponse;
-import org.apache.cloudstack.api.response.UserVmResponse;
-import org.apache.cloudstack.api.response.VolumeResponse;
-import org.apache.cloudstack.api.response.VpcOfferingResponse;
-import org.apache.cloudstack.api.response.ZoneResponse;
-import org.apache.cloudstack.backup.Backup;
-import org.apache.cloudstack.backup.BackupOffering;
-import org.apache.cloudstack.backup.BackupSchedule;
-import org.apache.cloudstack.backup.dao.BackupDao;
-import org.apache.cloudstack.backup.dao.BackupOfferingDao;
-import org.apache.cloudstack.backup.dao.BackupScheduleDao;
-import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
-import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.cloudstack.framework.jobs.AsyncJob;
-import org.apache.cloudstack.framework.jobs.AsyncJobManager;
-import org.apache.cloudstack.framework.jobs.dao.AsyncJobDao;
-import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
-import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
-import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
-
 import com.cloud.agent.api.VgpuTypesInfo;
 import com.cloud.api.query.dao.AccountJoinDao;
 import com.cloud.api.query.dao.AffinityGroupJoinDao;
@@ -163,6 +92,7 @@ import com.cloud.dc.dao.VlanDao;
 import com.cloud.domain.Domain;
 import com.cloud.domain.DomainVO;
 import com.cloud.domain.dao.DomainDao;
+import com.cloud.domain.dao.DomainDetailsDao;
 import com.cloud.event.Event;
 import com.cloud.event.dao.EventJoinDao;
 import com.cloud.exception.InvalidParameterValueException;
@@ -256,13 +186,16 @@ import com.cloud.projects.ProjectInvitation;
 import com.cloud.projects.ProjectService;
 import com.cloud.region.ha.GlobalLoadBalancingRulesService;
 import com.cloud.resource.ResourceManager;
+import com.cloud.resource.icon.ResourceIconVO;
+import com.cloud.resource.icon.dao.ResourceIconDao;
 import com.cloud.server.ManagementServer;
+import com.cloud.server.ResourceIcon;
+import com.cloud.server.ResourceManagerUtil;
 import com.cloud.server.ResourceMetaDataService;
 import com.cloud.server.ResourceTag;
 import com.cloud.server.ResourceTag.ResourceObjectType;
 import com.cloud.server.StatsCollector;
 import com.cloud.server.TaggedResourceService;
-import com.cloud.server.ResourceManagerUtil;
 import com.cloud.service.ServiceOfferingDetailsVO;
 import com.cloud.service.ServiceOfferingVO;
 import com.cloud.service.dao.ServiceOfferingDao;
@@ -340,6 +273,72 @@ import com.cloud.vm.dao.UserVmDetailsDao;
 import com.cloud.vm.dao.VMInstanceDao;
 import com.cloud.vm.snapshot.VMSnapshot;
 import com.cloud.vm.snapshot.dao.VMSnapshotDao;
+import org.apache.cloudstack.acl.Role;
+import org.apache.cloudstack.acl.RoleService;
+import org.apache.cloudstack.affinity.AffinityGroup;
+import org.apache.cloudstack.affinity.AffinityGroupResponse;
+import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants.DomainDetails;
+import org.apache.cloudstack.api.ApiConstants.HostDetails;
+import org.apache.cloudstack.api.ApiConstants.VMDetails;
+import org.apache.cloudstack.api.ResponseObject.ResponseView;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AsyncJobResponse;
+import org.apache.cloudstack.api.response.BackupOfferingResponse;
+import org.apache.cloudstack.api.response.BackupResponse;
+import org.apache.cloudstack.api.response.BackupScheduleResponse;
+import org.apache.cloudstack.api.response.DiskOfferingResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.DomainRouterResponse;
+import org.apache.cloudstack.api.response.EventResponse;
+import org.apache.cloudstack.api.response.HostForMigrationResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.HostTagResponse;
+import org.apache.cloudstack.api.response.ImageStoreResponse;
+import org.apache.cloudstack.api.response.InstanceGroupResponse;
+import org.apache.cloudstack.api.response.NetworkOfferingResponse;
+import org.apache.cloudstack.api.response.ProjectAccountResponse;
+import org.apache.cloudstack.api.response.ProjectInvitationResponse;
+import org.apache.cloudstack.api.response.ProjectResponse;
+import org.apache.cloudstack.api.response.ResourceIconResponse;
+import org.apache.cloudstack.api.response.ResourceTagResponse;
+import org.apache.cloudstack.api.response.SecurityGroupResponse;
+import org.apache.cloudstack.api.response.ServiceOfferingResponse;
+import org.apache.cloudstack.api.response.StoragePoolResponse;
+import org.apache.cloudstack.api.response.StorageTagResponse;
+import org.apache.cloudstack.api.response.TemplateResponse;
+import org.apache.cloudstack.api.response.UserResponse;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.VolumeResponse;
+import org.apache.cloudstack.api.response.VpcOfferingResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.backup.Backup;
+import org.apache.cloudstack.backup.BackupOffering;
+import org.apache.cloudstack.backup.BackupSchedule;
+import org.apache.cloudstack.backup.dao.BackupDao;
+import org.apache.cloudstack.backup.dao.BackupOfferingDao;
+import org.apache.cloudstack.backup.dao.BackupScheduleDao;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.framework.jobs.AsyncJob;
+import org.apache.cloudstack.framework.jobs.AsyncJobManager;
+import org.apache.cloudstack.framework.jobs.dao.AsyncJobDao;
+import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
 
 public class ApiDBUtils {
     private static ManagementServer s_ms;
@@ -407,6 +406,7 @@ public class ApiDBUtils {
     static ResourceLimitService s_resourceLimitMgr;
     static ProjectService s_projectMgr;
     static ResourceManager s_resourceMgr;
+    static DomainDetailsDao s_domainDetailsDao;
     static AccountDetailsDao s_accountDetailsDao;
     static NetworkDomainDao s_networkDomainDao;
     static HighAvailabilityManager s_haMgr;
@@ -596,6 +596,8 @@ public class ApiDBUtils {
     @Inject
     private ResourceManager resourceMgr;
     @Inject
+    private DomainDetailsDao domainDetailsDao;
+    @Inject
     private AccountDetailsDao accountDetailsDao;
     @Inject
     private NetworkDomainDao networkDomainDao;
@@ -784,6 +786,7 @@ public class ApiDBUtils {
         s_resourceLimitMgr = resourceLimitMgr;
         s_projectMgr = projectMgr;
         s_resourceMgr = resourceMgr;
+        s_domainDetailsDao = domainDetailsDao;
         s_accountDetailsDao = accountDetailsDao;
         s_networkDomainDao = networkDomainDao;
         s_haMgr = haMgr;
@@ -1436,6 +1439,11 @@ public class ApiDBUtils {
         return s_projectMgr.getProjectOwner(projectId).getId();
     }
 
+    public static Map<String, String> getDomainDetails(long domainId) {
+        Map<String, String> details = s_domainDetailsDao.findDetails(domainId);
+        return details.isEmpty() ? null : details;
+    }
+
     public static Map<String, String> getAccountDetails(long accountId) {
         Map<String, String> details = s_accountDetailsDao.findDetails(accountId);
         return details.isEmpty() ? null : details;
diff --git a/server/src/main/java/com/cloud/api/query/dao/DomainJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/DomainJoinDaoImpl.java
index ff0736e..529761a 100644
--- a/server/src/main/java/com/cloud/api/query/dao/DomainJoinDaoImpl.java
+++ b/server/src/main/java/com/cloud/api/query/dao/DomainJoinDaoImpl.java
@@ -102,6 +102,7 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem
             domainResponse.setProjectAvailable(projectAvail);
         }
 
+        domainResponse.setDetails(ApiDBUtils.getDomainDetails(domain.getId()));
         domainResponse.setObjectName("domain");
 
         return domainResponse;
diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
index 4e9828a..08ba1a3 100755
--- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -443,6 +443,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
     public static final ConfigKey<Boolean> SET_HOST_DOWN_TO_MAINTENANCE = new ConfigKey<Boolean>(Boolean.class, "set.host.down.to.maintenance", "Advanced", "false",
                         "Indicates whether the host in down state can be put into maintenance state so thats its not enabled after it comes back.",
                         true, ConfigKey.Scope.Zone, null);
+    public static final ConfigKey<Boolean> ENABLE_ACCOUNT_SETTINGS_FOR_DOMAIN = new ConfigKey<Boolean>(Boolean.class, "enable.account.settings.for.domain", "Advanced", "false",
+            "Indicates whether to add account settings for domain. If true, account settings will be added to domain settings, all accounts in the domain will inherit the domain setting if account setting is not set.", true, ConfigKey.Scope.Global, null);
+    public static final ConfigKey<Boolean> ENABLE_DOMAIN_SETTINGS_FOR_CHILD_DOMAIN = new ConfigKey<Boolean>(Boolean.class, "enable.domain.settings.for.child.domain", "Advanced", "false",
+            "Indicates whether the settings of parent domain should be applied for child domain. If true, the child domain will get value from parent domain if its not configured in child domain else global value is taken.",
+            true, ConfigKey.Scope.Global, null);
 
     public static ConfigKey<Integer> VM_SERVICE_OFFERING_MAX_CPU_CORES = new ConfigKey<Integer>("Advanced", Integer.class, "vm.serviceoffering.cpu.cores.max", "0", "Maximum CPU cores "
       + "for vm service offering. If 0 - no limitation", true);
@@ -884,7 +889,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
 
         final String configScope = cfg.getScope();
         if (scope != null) {
-            if (!configScope.contains(scope)) {
+            if (!configScope.contains(scope) &&
+                    !(ENABLE_ACCOUNT_SETTINGS_FOR_DOMAIN.value() && configScope.contains(ConfigKey.Scope.Account.toString()) &&
+                            scope.equals(ConfigKey.Scope.Domain.toString()))) {
                 s_logger.error("Invalid scope id provided for the parameter " + name);
                 return "Invalid scope id provided for the parameter " + name;
             }
@@ -7040,6 +7047,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
     public ConfigKey<?>[] getConfigKeys() {
         return new ConfigKey<?>[] {SystemVMUseLocalStorage, IOPS_MAX_READ_LENGTH, IOPS_MAX_WRITE_LENGTH,
                 BYTES_MAX_READ_LENGTH, BYTES_MAX_WRITE_LENGTH, ADD_HOST_ON_SERVICE_RESTART_KVM, SET_HOST_DOWN_TO_MAINTENANCE, VM_SERVICE_OFFERING_MAX_CPU_CORES,
-                VM_SERVICE_OFFERING_MAX_RAM_SIZE, VM_USERDATA_MAX_LENGTH, MIGRATE_VM_ACROSS_CLUSTERS};
+                VM_SERVICE_OFFERING_MAX_RAM_SIZE, VM_USERDATA_MAX_LENGTH, MIGRATE_VM_ACROSS_CLUSTERS,
+                ENABLE_ACCOUNT_SETTINGS_FOR_DOMAIN, ENABLE_DOMAIN_SETTINGS_FOR_CHILD_DOMAIN
+        };
     }
 }
diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
index e0db746..08ae0ad 100644
--- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
@@ -598,6 +598,7 @@ import com.cloud.capacity.dao.CapacityDao;
 import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity;
 import com.cloud.cluster.ClusterManager;
 import com.cloud.configuration.Config;
+import com.cloud.configuration.ConfigurationManagerImpl;
 import com.cloud.consoleproxy.ConsoleProxyManagementState;
 import com.cloud.consoleproxy.ConsoleProxyManager;
 import com.cloud.dc.AccountVlanMapVO;
@@ -2041,7 +2042,12 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
 
         if (scope != null && !scope.isEmpty()) {
             // getting the list of parameters at requested scope
-            sc.addAnd("scope", SearchCriteria.Op.EQ, scope);
+            if (ConfigurationManagerImpl.ENABLE_ACCOUNT_SETTINGS_FOR_DOMAIN.value()
+                && scope.equals(ConfigKey.Scope.Domain.toString())) {
+                sc.addAnd("scope", SearchCriteria.Op.IN, ConfigKey.Scope.Domain.toString(), ConfigKey.Scope.Account.toString());
+            } else {
+                sc.addAnd("scope", SearchCriteria.Op.EQ, scope);
+            }
         }
 
         final Pair<List<ConfigurationVO>, Integer> result = _configDao.searchAndCount(sc, searchFilter);
@@ -2054,7 +2060,13 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
                 if (configVo != null) {
                     final ConfigKey<?> key = _configDepot.get(param.getName());
                     if (key != null) {
-                        configVo.setValue(key.valueIn(id) == null ? null : key.valueIn(id).toString());
+                        if (scope.equals(ConfigKey.Scope.Domain.toString())) {
+                            Object value = key.valueInDomain(id);
+                            configVo.setValue(value == null ? null : value.toString());
+                        } else {
+                            Object value = key.valueIn(id);
+                            configVo.setValue(value == null ? null : value.toString());
+                        }
                         configVOList.add(configVo);
                     } else {
                         s_logger.warn("ConfigDepot could not find parameter " + param.getName() + " for scope " + scope);
diff --git a/test/integration/smoke/test_enable_account_settings_for_domain.py b/test/integration/smoke/test_enable_account_settings_for_domain.py
new file mode 100644
index 0000000..09550ed
--- /dev/null
+++ b/test/integration/smoke/test_enable_account_settings_for_domain.py
@@ -0,0 +1,514 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Import Local Modules
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase, unittest
+from marvin.lib.utils import (validateList,
+                              cleanup_resources)
+from marvin.lib.base import (Account,
+                             Configurations,
+                             Domain)
+from marvin.lib.common import (get_domain,
+                               get_zone)
+
+class TestDedicatePublicIPRange(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(self):
+        self.testClient = super(
+            TestDedicatePublicIPRange,
+            self).getClsTestClient()
+        self.apiclient = self.testClient.getApiClient()
+        self.testdata = self.testClient.getParsedTestDataConfig()
+        self.hypervisor = self.testClient.getHypervisorInfo()
+        # Get Zone, Domain
+        self.domain = get_domain(self.apiclient)
+        self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests())
+        self._cleanup = []
+        return
+
+    @classmethod
+    def tearDownClass(self):
+        try:
+            # Cleanup resources used
+            cleanup_resources(self.apiclient, self._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    def setUp(self):
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+        self.cleanup = []
+
+        return
+
+    def tearDown(self):
+        try:
+            # Clean up
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @attr(tags=["advanced", "advancedsg"], required_hardware="false")
+    def test_01_disable_account_settings_for_domain(self):
+        """Disable account settings for domain
+
+        # Validate the following:
+        # (1) Change global setting enable.account.settings.for.domain to false (default value)
+        # (2) create domain/account
+        # (3) list global settings vmsnapshot.expire.interval and get value (original value)
+        # (4) list account settings with name=(3), value should be same as (3)
+        # (5) list domain settings with name=(3), should return null/empty
+        # (6) change global settings (3) to original +10
+        # (7) list account settings with name=(3), value should be same as (6)
+        # (8) change account settings (4) to original +20
+        # (9) list account settings with name=(3), value should be same as (8)
+        # (10) update domain settings with name=(3), should get exception
+        # (11) reset vmsnapshot.expire.interval to original value (3)
+        """
+
+        config_name = "vmsnapshot.expire.interval"
+
+        # (1) Change global setting enable.account.settings.for.domain to false (default value)
+        Configurations.update(
+            self.apiclient,
+            name="enable.account.settings.for.domain",
+            value="false"
+        )
+        Configurations.update(
+            self.apiclient,
+            name="enable.domain.settings.for.child.domain",
+            value="false"
+        )
+
+        # (2) create domain/account
+        user_domain = Domain.create(
+            self.apiclient,
+            services=self.testdata["acl"]["domain2"],
+            parentdomainid=self.domain.id)
+        account = Account.create(
+            self.apiclient,
+            self.testdata["acl"]["accountD2"],
+            domainid=user_domain.id
+        )
+        self.cleanup.append(account)
+        self.cleanup.append(user_domain)
+
+        # (3) list global settings vmsnapshot.expire.interval and get value (original value)
+        configs = Configurations.list(
+            self.apiclient,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get global setting %s " % config_name)
+        orig_value = int(configs[0].value)
+
+        # (4) list account settings with name=(3), value should be same as (3)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(orig_value, account_value, "Account setting is not equal to global setting")
+
+        # (5) list domain settings with name=(3), should return null/empty
+        configs = Configurations.list(
+            self.apiclient,
+            domainid=user_domain.id,
+            name=config_name)
+        self.assertIsNone(configs, "Domain setting %s should not exist" % config_name)
+
+        # (6) change global settings (3) to original +10
+        new_value = orig_value + 10
+        Configurations.update(
+            self.apiclient,
+            name=config_name,
+            value=new_value
+        )
+
+        # (7) list account settings with name=(3), value should be same as (6)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(new_value, account_value, "Account setting is not equal to new value of global setting")
+
+        # (8) change account settings (4) to original +20
+        new_value = orig_value + 20
+        Configurations.update(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name,
+            value=new_value
+        )
+
+        # (9) list account settings with name=(3), value should be same as (8)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(new_value, account_value, "Account setting is not equal to new value of account setting")
+
+        # (10) update domain settings with name=(3), should get exception
+        try:
+            Configurations.update(
+                self.apiclient,
+                domainid=user_domain.id,
+                name=config_name,
+                value=new_value
+            )
+            self.fail("Updating domain setting should fail")
+        except Exception as e:
+            self.debug("Updating domain setting failed as expected with Exception %s" % e)
+
+        # (11) reset vmsnapshot.expire.interval to original value (3)
+        Configurations.update(
+            self.apiclient,
+            name=config_name,
+            value=orig_value
+        )
+
+        return
+
+    @attr(tags=["advanced", "advancedsg"], required_hardware="false")
+    def test_02_enable_account_settings_for_domain(self):
+        """Enable account settings for domain
+
+        # Validate the following:
+        # (1) Change global setting enable.account.settings.for.domain to true
+        # (2) create domain/account
+        # (3) list global settings vmsnapshot.expire.interval and get value (original value)
+        # (4) list domain settings with name=(3), value should be same as (3)
+        # (5) list account settings with name=(3), value should be same as (4) = (5)
+        # (6) change global settings (3) to original +10
+        # (7) list domain settings with name=(3), value should be same as (6)
+        # (8) list account settings with name=(3), value should be same as (6)=(7)
+        # (9) change ROOT domain settings (4) to original +20
+        # (10) list domain settings with name=(3), value should be same as (9)
+        # (11) list account settings with name=(3), value should be same as (9)=(10)
+        # (12) change domain settings (4) to original +30
+        # (13) list domain settings with name=(3), value should be same as (12)
+        # (14) list account settings with name=(3), value should be same as (12)=(13)
+        # (15) change account settings (4) to original +40
+        # (16) list account settings with name=(3), value should be same as (15)
+        # (17) reset vmsnapshot.expire.interval to original value (3)
+        """
+
+        config_name = "vmsnapshot.expire.interval"
+
+        # (1) Change global setting enable.account.settings.for.domain to true
+        Configurations.update(
+            self.apiclient,
+            name="enable.account.settings.for.domain",
+            value="true"
+        )
+
+        # (2) create domain/account
+        user_domain = Domain.create(
+            self.apiclient,
+            services=self.testdata["acl"]["domain2"],
+            parentdomainid=self.domain.id)
+        account = Account.create(
+            self.apiclient,
+            self.testdata["acl"]["accountD2"],
+            domainid=user_domain.id
+        )
+        self.cleanup.append(account)
+        self.cleanup.append(user_domain)
+
+        # (3) list global settings vmsnapshot.expire.interval and get value (original value)
+        configs = Configurations.list(
+            self.apiclient,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get global setting %s " % config_name)
+        orig_value = int(configs[0].value)
+
+        # (4) list domain settings with name=(3), value should be same as (3)
+        configs = Configurations.list(
+            self.apiclient,
+            domainid=user_domain.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name)
+        domain_value = int(configs[0].value)
+        self.assertEqual(orig_value, domain_value, "Domain setting is not equal to global setting")
+
+        # (5) list account settings with name=(3), value should be same as (4) = (5)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(orig_value, account_value, "Account setting is not equal to global setting")
+
+        # (6) change global settings (3) to original +10
+        new_value = orig_value + 10
+        Configurations.update(
+            self.apiclient,
+            name=config_name,
+            value=new_value
+        )
+
+        # (7) list domain settings with name=(3), value should be same as (6)
+        configs = Configurations.list(
+            self.apiclient,
+            domainid=user_domain.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name)
+        domain_value = int(configs[0].value)
+        self.assertEqual(new_value, domain_value, "Domain setting is not equal to new value of global setting")
+
+        # (8) list account settings with name=(3), value should be same as (6)=(7)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(new_value, account_value, "Account setting is not equal to new value of global setting")
+
+        old_domain_value = new_value
+
+        # (9) change ROOT domain settings (4) to original +20
+        new_value = orig_value + 20
+        Configurations.update(
+            self.apiclient,
+            domainid=self.domain.id,
+            name=config_name,
+            value=new_value
+        )
+
+        # (10) list domain settings with name=(3), value should be same as (9)
+        configs = Configurations.list(
+            self.apiclient,
+            domainid=user_domain.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name)
+        domain_value = int(configs[0].value)
+        self.assertEqual(old_domain_value, domain_value, "Domain setting is not equal to new value of ROOT domain setting")
+
+        # (11) list account settings with name=(3), value should be same as (9)=(10)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(old_domain_value, account_value, "Account setting is not equal to new value of ROOT domain setting")
+
+        # (12) change domain settings (4) to original +30
+        new_value = orig_value + 30
+        Configurations.update(
+            self.apiclient,
+            domainid=user_domain.id,
+            name=config_name,
+            value=new_value
+        )
+
+        # (13) list domain settings with name=(3), value should be same as (12)
+        configs = Configurations.list(
+            self.apiclient,
+            domainid=user_domain.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name)
+        domain_value = int(configs[0].value)
+        self.assertEqual(new_value, domain_value, "Domain setting is not equal to new value of domain setting")
+
+        # (14) list account settings with name=(3), value should be same as (12)=(13)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(old_domain_value, account_value, "Account setting is not equal to new value of domain setting")
+
+        # (15) change account settings (4) to original +40
+        new_value = orig_value + 40
+        Configurations.update(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name,
+            value=new_value
+        )
+
+        # (16) list account settings with name=(3), value should be same as (15)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(new_value, account_value, "Account setting is not equal to new value of account setting")
+
+        # (17) reset vmsnapshot.expire.interval to original value (3)
+        Configurations.update(
+            self.apiclient,
+            name=config_name,
+            value=orig_value
+        )
+
+        Configurations.update(
+            self.apiclient,
+            name="enable.account.settings.for.domain",
+            value="false"
+        )
+
+        return
+
+    @attr(tags=["advanced", "advancedsg"], required_hardware="false")
+    def test_03_enable_account_settings_for_domain(self):
+        """Enable account settings for domain
+
+        # Validate the following:
+        # (1) Change global setting enable.account.settings.for.domain to true
+        # (2) create domain/account
+        # (3) list global settings vmsnapshot.expire.interval and get value (original value)
+        # (4) list domain settings with name=(3), value should be same as (3)
+        # (5) list account settings with name=(3), value should be same as (4) = (5)
+        # (6) change global settings (3) to original +10
+        # (7) change global setting enable.domain.settings.for.child.domain to true
+        # (8) change domain setting (3) to original +30
+        # (9) list domain settings with name=(3), value should be same as (8)
+        # (10) list account settings with name=(3), value should be same as (9)=(8)
+        # (11) change acount setting (3) to original +50
+        # (12) list account settings with name=(3), value should be same as (10)
+        """
+
+        config_name = "vmsnapshot.expire.interval"
+
+        # (1) Change global setting enable.account.settings.for.domain to true
+        Configurations.update(
+            self.apiclient,
+            name="enable.account.settings.for.domain",
+            value="true"
+        )
+
+        # (2) create domain/account
+        user_domain = Domain.create(
+            self.apiclient,
+            services=self.testdata["acl"]["domain2"],
+            parentdomainid=self.domain.id)
+        account = Account.create(
+            self.apiclient,
+            self.testdata["acl"]["accountD2"],
+            domainid=user_domain.id
+        )
+        self.cleanup.append(account)
+        self.cleanup.append(user_domain)
+
+        # (3) list global settings vmsnapshot.expire.interval and get value (original value)
+        configs = Configurations.list(
+            self.apiclient,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get global setting %s " % config_name)
+        orig_value = int(configs[0].value)
+
+        # (4) list domain settings with name=(3), value should be same as (3)
+        configs = Configurations.list(
+            self.apiclient,
+            domainid=user_domain.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name)
+        domain_value = int(configs[0].value)
+        self.assertEqual(orig_value, domain_value, "Domain setting is not equal to global setting")
+
+        # (5) list account settings with name=(3), value should be same as (4) = (5)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(orig_value, account_value, "Account setting is not equal to global setting")
+
+        # (6) change global settings (3) to original +10
+        new_value = orig_value + 10
+        Configurations.update(
+            self.apiclient,
+            name=config_name,
+            value=new_value
+        )
+
+        # (7) change global setting enable.domain.settings.for.child.domain to true
+        Configurations.update(
+            self.apiclient,
+            name="enable.domain.settings.for.child.domain",
+            value="true"
+        )
+
+        # (8) change domain setting (3) to original +30
+        new_domain_value = domain_value + 30
+        Configurations.update(
+            self.apiclient,
+            name=config_name,
+            domainid=user_domain.id,
+            value=new_domain_value
+        )
+
+        # (9) list domain settings with name=(3), value should be same as (8)
+        configs = Configurations.list(
+            self.apiclient,
+            domainid=user_domain.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get domain setting %s " % config_name)
+        domain_value = int(configs[0].value)
+        self.assertEqual(new_domain_value, domain_value, "Domain setting is not equal to new value of global setting")
+
+        # (10) list account settings with name=(3), value should be same as (9)=(8)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(new_domain_value, account_value, "Account setting is not equal to new value of global setting")
+
+        # (11) change acount setting (3) to original +50
+        new_account_value = account_value + 50
+        Configurations.update(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name,
+            value=new_account_value
+        )
+
+        # (12) list account settings with name=(3), value should be same as (10)
+        configs = Configurations.list(
+            self.apiclient,
+            accountid=account.id,
+            name=config_name)
+        self.assertIsNotNone(configs, "Fail to get account setting %s " % config_name)
+        account_value = int(configs[0].value)
+        self.assertEqual(new_account_value, account_value, "Account setting is not equal to new value of global setting")
+
+        Configurations.update(
+            self.apiclient,
+            name="enable.account.settings.for.domain",
+            value="false"
+        )
+        Configurations.update(
+            self.apiclient,
+            name="enable.domain.settings.for.child.domain",
+            value="false"
+        )