You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2018/01/06 17:28:34 UTC

[cloudstack] branch master updated: CLOUDSTACK-10117: Account ldap binding (#2381)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 45df928  CLOUDSTACK-10117: Account ldap binding (#2381)
45df928 is described below

commit 45df928e0430745b55d270c1e79d244f35ac1b5e
Author: dahn <da...@gmail.com>
AuthorDate: Sat Jan 6 18:28:28 2018 +0100

    CLOUDSTACK-10117: Account ldap binding (#2381)
    
    Map an ldap group to an account. Ldap related settings on a domain level.
---
 .../api/command/admin/config/ListCfgsByCmd.java    |  14 +
 .../api/command/admin/config/UpdateCfgCmd.java     |  14 +
 .../spring-engine-schema-core-daos-context.xml     |   1 +
 .../resources/META-INF/db/schema-41000to41100.sql  |  19 +-
 .../src/com/cloud/domain/DomainDetailVO.java       |  56 ++--
 .../src/com/cloud/domain/dao/DomainDetailsDao.java |  22 +-
 .../com/cloud/domain/dao/DomainDetailsDaoImpl.java | 104 ++++++++
 .../cloudstack/framework/config/ConfigKey.java     |   2 +-
 .../framework/config/impl/ConfigDepotImpl.java     |   1 +
 .../management/IntegrationTestConfiguration.java   |   7 +-
 .../contrail/management/MockAccountManager.java    |   8 +-
 plugins/user-authenticators/ldap/pom.xml           |   8 +-
 .../cloudstack/api/command/LDAPConfigCmd.java      |   8 +-
 .../cloudstack/api/command/LDAPRemoveCmd.java      |   4 +-
 .../api/command/LdapAddConfigurationCmd.java       |  15 +-
 .../api/command/LdapCreateAccountCmd.java          |   2 +-
 .../api/command/LdapDeleteConfigurationCmd.java    |  25 +-
 .../cloudstack/api/command/LdapImportUsersCmd.java |   4 +-
 .../api/command/LdapListConfigurationCmd.java      |  17 +-
 .../cloudstack/api/command/LdapListUsersCmd.java   |   2 +-
 ...ainToLdapCmd.java => LinkAccountToLdapCmd.java} |  82 ++++--
 .../api/command/LinkDomainToLdapCmd.java           |  29 +-
 .../api/response/LdapConfigurationResponse.java    |  35 ++-
 ...esponse.java => LinkAccountToLdapResponse.java} |  26 +-
 .../api/response/LinkDomainToLdapResponse.java     |   5 -
 .../cloudstack/ldap/ADLdapUserManagerImpl.java     |  22 +-
 .../apache/cloudstack/ldap/LdapAuthenticator.java  | 205 ++++++++++++---
 .../apache/cloudstack/ldap/LdapConfiguration.java  | 292 ++++++++++++++++-----
 .../cloudstack/ldap/LdapConfigurationVO.java       |  10 +-
 .../apache/cloudstack/ldap/LdapContextFactory.java |  38 +--
 .../org/apache/cloudstack/ldap/LdapManager.java    |  38 ++-
 .../apache/cloudstack/ldap/LdapManagerImpl.java    | 161 +++++++++---
 .../org/apache/cloudstack/ldap/LdapTrustMapVO.java |  14 +-
 .../src/org/apache/cloudstack/ldap/LdapUser.java   |  11 +-
 .../apache/cloudstack/ldap/LdapUserManager.java    |  14 +-
 .../src/org/apache/cloudstack/ldap/LdapUtils.java  |  15 ++
 .../cloudstack/ldap/OpenLdapUserManagerImpl.java   | 104 ++++----
 .../cloudstack/ldap/dao/LdapConfigurationDao.java  |  13 +-
 .../ldap/dao/LdapConfigurationDaoImpl.java         |  43 ++-
 .../cloudstack/ldap/dao/LdapTrustMapDao.java       |   5 +
 .../cloudstack/ldap/dao/LdapTrustMapDaoImpl.java   |  34 +++
 .../ldap/ADLdapUserManagerImplSpec.groovy          |   6 +-
 .../cloudstack/ldap/LdapAuthenticatorSpec.groovy   |  22 +-
 .../ldap/LdapConfigurationDaoImplSpec.groovy       |   4 +-
 .../cloudstack/ldap/LdapConfigurationSpec.groovy   | 112 +-------
 .../cloudstack/ldap/LdapContextFactorySpec.groovy  |  11 +-
 .../ldap/LdapCreateAccountCmdSpec.groovy           |  51 +---
 .../ldap/LdapDeleteConfigurationCmdSpec.groovy     |   4 +-
 .../cloudstack/ldap/LdapImportUsersCmdSpec.groovy  |  42 ++-
 .../cloudstack/ldap/LdapListUsersCmdSpec.groovy    |  10 +-
 .../cloudstack/ldap/LdapManagerImplSpec.groovy     |  36 +--
 .../cloudstack/ldap/LdapSearchUserCmdSpec.groovy   |   2 +-
 .../org/apache/cloudstack/ldap/LdapUserSpec.groovy |  22 +-
 .../cloudstack/ldap/LinkDomainToLdapCmdSpec.groovy |   6 +-
 .../cloudstack/ldap/OpenLdapUserManagerSpec.groovy |  14 +-
 .../api/command/LdapConfigurationChanger.java      |  56 ++++
 .../api/command/LdapCreateAccountCmdTest.java      |  72 +++++
 .../api/command/LdapImportUsersCmdTest.java        |  85 ++++++
 .../api/command/LinkAccountToLdapCmdTest.java      |  97 +++++++
 .../api/command/LinkDomainToLdapCmdTest.java       |  98 +++++++
 .../cloudstack/ldap/LdapConfigurationTest.java     | 141 ++++++++++
 server/src/com/cloud/configuration/Config.java     |  59 +----
 .../configuration/ConfigurationManagerImpl.java    |  25 ++
 .../src/com/cloud/server/ManagementServerImpl.java |   6 +
 server/src/com/cloud/user/AccountManager.java      |   2 +
 server/src/com/cloud/user/AccountManagerImpl.java  |  40 ++-
 .../com/cloud/user/MockAccountManagerImpl.java     |   8 +-
 .../networkoffering/ChildTestConfiguration.java    |  60 +++--
 ui/scripts/domains.js                              |  90 ++++---
 69 files changed, 1985 insertions(+), 725 deletions(-)

diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java
index 8f71f48..80ebaf4 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java
@@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command.admin.config;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.cloudstack.api.response.DomainResponse;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.api.APICommand;
@@ -77,6 +78,12 @@ public class ListCfgsByCmd extends BaseListCmd {
                description = "the ID of the Account to update the parameter value for corresponding account")
     private Long accountId;
 
+    @Parameter(name = ApiConstants.DOMAIN_ID,
+               type = CommandType.UUID,
+               entityType = DomainResponse.class,
+               description = "the ID of the Domain to update the parameter value for corresponding domain")
+    private Long domainId;
+
     @Parameter(name = ApiConstants.IMAGE_STORE_UUID,
             type = CommandType.UUID,
             entityType = ImageStoreResponse.class,
@@ -111,6 +118,10 @@ public class ListCfgsByCmd extends BaseListCmd {
         return accountId;
     }
 
+    public Long getDomainId() {
+        return domainId;
+    }
+
     public Long getImageStoreId() {
         return imageStoreId;
     }
@@ -158,6 +169,9 @@ public class ListCfgsByCmd extends BaseListCmd {
             if (getAccountId() != null) {
                 cfgResponse.setScope("account");
             }
+            if (getDomainId() != null) {
+                cfgResponse.setScope("domain");
+            }
             if (getImageStoreId() != null){
                 cfgResponse.setScope("imagestore");
             }
diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java
index fa5e26e..936f0cd 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java
@@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.admin.config;
 
 import com.google.common.base.Strings;
 import org.apache.cloudstack.acl.RoleService;
+import org.apache.cloudstack.api.response.DomainResponse;
 import org.apache.log4j.Logger;
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiArgValidator;
@@ -76,6 +77,12 @@ public class UpdateCfgCmd extends BaseCmd {
                description = "the ID of the Account to update the parameter value for corresponding account")
     private Long accountId;
 
+    @Parameter(name = ApiConstants.DOMAIN_ID,
+               type = CommandType.UUID,
+               entityType = DomainResponse.class,
+               description = "the ID of the Domain to update the parameter value for corresponding domain")
+    private Long domainId;
+
     @Parameter(name = ApiConstants.IMAGE_STORE_UUID,
             type = CommandType.UUID,
             entityType = ImageStoreResponse.class,
@@ -115,6 +122,10 @@ public class UpdateCfgCmd extends BaseCmd {
         return accountId;
     }
 
+    public Long getDomainId() {
+        return domainId;
+    }
+
     public Long getImageStoreId() {
         return imageStoreId;
     }
@@ -157,6 +168,9 @@ public class UpdateCfgCmd extends BaseCmd {
             if (getAccountId() != null) {
                 response.setScope("account");
             }
+            if (getDomainId() != null) {
+                response.setScope("domain");
+            }
             response.setValue(value);
             this.setResponseObject(response);
         } else {
diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
index 8a0d7cd..84c2758 100644
--- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
+++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
@@ -147,6 +147,7 @@
   <bean id="engineDcDetailsDaoImpl" class="org.apache.cloudstack.engine.datacenter.entity.api.db.dao.DcDetailsDaoImpl" />
   <bean id="diskOfferingJoinDaoImpl" class="com.cloud.api.query.dao.DiskOfferingJoinDaoImpl" />
   <bean id="domainDaoImpl" class="com.cloud.domain.dao.DomainDaoImpl" />
+  <bean id="domainDetailsDaoImpl" class="com.cloud.domain.dao.DomainDetailsDaoImpl" />
   <bean id="domainJoinDaoImpl" class="com.cloud.api.query.dao.DomainJoinDaoImpl" />
   <bean id="domainRouterDaoImpl" class="com.cloud.vm.dao.DomainRouterDaoImpl" />
   <bean id="domainRouterJoinDaoImpl" class="com.cloud.api.query.dao.DomainRouterJoinDaoImpl" />
diff --git a/engine/schema/resources/META-INF/db/schema-41000to41100.sql b/engine/schema/resources/META-INF/db/schema-41000to41100.sql
index 585c7fd..283844e 100644
--- a/engine/schema/resources/META-INF/db/schema-41000to41100.sql
+++ b/engine/schema/resources/META-INF/db/schema-41000to41100.sql
@@ -451,7 +451,7 @@ CREATE VIEW `cloud`.`volume_view` AS
         `cloud`.`domain` resource_tag_domain ON resource_tag_domain.id = resource_tags.domain_id;
 
 -- Extra Dhcp Options
-CREATE TABLE `cloud`.`nic_extra_dhcp_options` (
+CREATE TABLE  IF NOT EXISTS `cloud`.`nic_extra_dhcp_options` (
   `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
   `uuid` varchar(255) UNIQUE,
   `nic_id` bigint unsigned NOT NULL COMMENT ' nic id where dhcp options are applied',
@@ -523,3 +523,20 @@ ADD COLUMN `forsystemvms` TINYINT(1) NOT NULL DEFAULT '0' COMMENT 'Indicates if
 
 ALTER TABLE `cloud`.`op_dc_ip_address_alloc`
 ADD COLUMN `vlan` INT(10) UNSIGNED NULL COMMENT 'Vlan the management network range is on';
+
+-- ldap binding on domain level
+CREATE TABLE IF NOT EXISTS `cloud`.`domain_details` (
+    `id` bigint unsigned NOT NULL auto_increment,
+    `domain_id` bigint unsigned NOT NULL COMMENT 'account id',
+    `name` varchar(255) NOT NULL,
+    `value` varchar(255) NOT NULL,
+    PRIMARY KEY (`id`),
+    CONSTRAINT `fk_domain_details__domain_id` FOREIGN KEY (`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE
+)ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+ALTER TABLE cloud.ldap_configuration ADD COLUMN domain_id BIGINT(20) DEFAULT NULL;
+ALTER TABLE cloud.ldap_trust_map ADD COLUMN account_id BIGINT(20) DEFAULT 0;
+ALTER TABLE cloud.ldap_trust_map DROP FOREIGN KEY fk_ldap_trust_map__domain_id;
+DROP INDEX uk_ldap_trust_map__domain_id ON cloud.ldap_trust_map;
+CREATE UNIQUE INDEX uk_ldap_trust_map__bind_location ON ldap_trust_map (domain_id, account_id);
+
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java b/engine/schema/src/com/cloud/domain/DomainDetailVO.java
similarity index 61%
copy from plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java
copy to engine/schema/src/com/cloud/domain/DomainDetailVO.java
index 488e7f4..61eb6cf 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java
+++ b/engine/schema/src/com/cloud/domain/DomainDetailVO.java
@@ -14,7 +14,7 @@
 // KIND, either express or implied.  See the License for the
 // specific language governing permissions and limitations
 // under the License.
-package org.apache.cloudstack.ldap;
+package com.cloud.domain;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -23,44 +23,54 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.Table;
 
+import com.cloud.utils.db.Encrypt;
 import org.apache.cloudstack.api.InternalIdentity;
 
 @Entity
-@Table(name = "ldap_configuration")
-public class LdapConfigurationVO implements InternalIdentity {
-    @Column(name = "hostname")
-    private String hostname;
-
+@Table(name = "domain_details")
+public class DomainDetailVO implements InternalIdentity {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Column(name = "id")
-    private Long id;
+    private long id;
+
+    @Column(name = "domain_id")
+    private long domainId;
+
+    @Column(name = "name")
+    private String name;
 
-    @Column(name = "port")
-    private int port;
+    @Encrypt
+    @Column(name = "value")
+    private String value;
 
-    public LdapConfigurationVO() {
+    protected DomainDetailVO() {
     }
 
-    public LdapConfigurationVO(final String hostname, final int port) {
-        this.hostname = hostname;
-        this.port = port;
+    public DomainDetailVO(long domainId, String name, String value) {
+        this.domainId = domainId;
+        this.name = name;
+        this.value = value;
     }
 
-    public String getHostname() {
-        return hostname;
+    public long getDomainId() {
+        return domainId;
     }
 
-    @Override
-    public long getId() {
-        return id;
+    public String getName() {
+        return name;
     }
 
-    public int getPort() {
-        return port;
+    public String getValue() {
+        return value;
     }
 
-    public void setId(final long id) {
-        this.id = id;
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public long getId() {
+        return id;
     }
-}
\ No newline at end of file
+}
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java b/engine/schema/src/com/cloud/domain/dao/DomainDetailsDao.java
similarity index 65%
copy from plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java
copy to engine/schema/src/com/cloud/domain/dao/DomainDetailsDao.java
index a2d5e65..51362cf 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java
+++ b/engine/schema/src/com/cloud/domain/dao/DomainDetailsDao.java
@@ -14,17 +14,21 @@
 // KIND, either express or implied.  See the License for the
 // specific language governing permissions and limitations
 // under the License.
-package org.apache.cloudstack.ldap.dao;
+package com.cloud.domain.dao;
 
-import java.util.List;
+import java.util.Map;
 
-import org.apache.cloudstack.ldap.LdapConfigurationVO;
-
-import com.cloud.utils.Pair;
+import com.cloud.domain.DomainDetailVO;
 import com.cloud.utils.db.GenericDao;
 
-public interface LdapConfigurationDao extends GenericDao<LdapConfigurationVO, Long> {
-    LdapConfigurationVO findByHostname(String hostname);
+public interface DomainDetailsDao extends GenericDao<DomainDetailVO, Long> {
+    Map<String, String> findDetails(long domainId);
+
+    void persist(long domainId, Map<String, String> details);
+
+    DomainDetailVO findDetail(long domainId, String name);
+
+    void deleteDetails(long domainId);
 
-    Pair<List<LdapConfigurationVO>, Integer> searchConfigurations(String hostname, int port);
-}
\ No newline at end of file
+    void update(long domainId, Map<String, String> details);
+}
diff --git a/engine/schema/src/com/cloud/domain/dao/DomainDetailsDaoImpl.java b/engine/schema/src/com/cloud/domain/dao/DomainDetailsDaoImpl.java
new file mode 100644
index 0000000..ad7f704
--- /dev/null
+++ b/engine/schema/src/com/cloud/domain/dao/DomainDetailsDaoImpl.java
@@ -0,0 +1,104 @@
+// 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.
+package com.cloud.domain.dao;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.cloud.domain.DomainDetailVO;
+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.ConfigKey;
+import org.apache.cloudstack.framework.config.ConfigKey.Scope;
+import org.apache.cloudstack.framework.config.ScopedConfigStorage;
+
+public class DomainDetailsDaoImpl extends GenericDaoBase<DomainDetailVO, Long> implements DomainDetailsDao, ScopedConfigStorage {
+    protected final SearchBuilder<DomainDetailVO> domainSearch;
+
+    protected DomainDetailsDaoImpl() {
+        domainSearch = createSearchBuilder();
+        domainSearch.and("domainId", domainSearch.entity().getDomainId(), Op.EQ);
+        domainSearch.done();
+    }
+
+    @Override
+    public Map<String, String> findDetails(long domainId) {
+        QueryBuilder<DomainDetailVO> sc = QueryBuilder.create(DomainDetailVO.class);
+        sc.and(sc.entity().getDomainId(), Op.EQ, domainId);
+        List<DomainDetailVO> results = sc.list();
+        Map<String, String> details = new HashMap<String, String>(results.size());
+        for (DomainDetailVO r : results) {
+            details.put(r.getName(), r.getValue());
+        }
+        return details;
+    }
+
+    @Override
+    public void persist(long domainId, Map<String, String> details) {
+        TransactionLegacy txn = TransactionLegacy.currentTxn();
+        txn.start();
+        SearchCriteria<DomainDetailVO> sc = domainSearch.create();
+        sc.setParameters("domainId", domainId);
+        expunge(sc);
+        for (Map.Entry<String, String> detail : details.entrySet()) {
+            DomainDetailVO vo = new DomainDetailVO(domainId, detail.getKey(), detail.getValue());
+            persist(vo);
+        }
+        txn.commit();
+    }
+
+    @Override
+    public DomainDetailVO findDetail(long domainId, String name) {
+        QueryBuilder<DomainDetailVO> sc = QueryBuilder.create(DomainDetailVO.class);
+        sc.and(sc.entity().getDomainId(), Op.EQ, domainId);
+        sc.and(sc.entity().getName(), Op.EQ, name);
+        return sc.find();
+    }
+
+    @Override
+    public void deleteDetails(long domainId) {
+        SearchCriteria<DomainDetailVO> sc = domainSearch.create();
+        sc.setParameters("domainId", domainId);
+        List<DomainDetailVO> results = search(sc, null);
+        for (DomainDetailVO result : results) {
+            remove(result.getId());
+        }
+    }
+
+    @Override
+    public void update(long domainId, Map<String, String> details) {
+        Map<String, String> oldDetails = findDetails(domainId);
+        oldDetails.putAll(details);
+        persist(domainId, oldDetails);
+    }
+
+    @Override
+    public Scope getScope() {
+        return Scope.Domain;
+    }
+
+    @Override
+    public String getConfigValue(long id, ConfigKey<?> key) {
+        DomainDetailVO vo = findDetail(id, key.key());
+        return vo == null ? null : vo.getValue();
+    }
+}
diff --git a/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java b/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java
index fb2a57b..1734b98 100644
--- a/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java
+++ b/framework/config/src/org/apache/cloudstack/framework/config/ConfigKey.java
@@ -31,7 +31,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
 public class ConfigKey<T> {
 
     public static enum Scope {
-        Global, Zone, Cluster, StoragePool, Account, ManagementServer, ImageStore
+        Global, Zone, Cluster, StoragePool, Account, ManagementServer, ImageStore, Domain
     }
 
     private final String _category;
diff --git a/framework/config/src/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java b/framework/config/src/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java
index e68fd3c..6a85b90 100644
--- a/framework/config/src/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java
+++ b/framework/config/src/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java
@@ -85,6 +85,7 @@ public class ConfigDepotImpl implements ConfigDepot, ConfigDepotAdmin {
         _scopeLevelConfigsMap.put(ConfigKey.Scope.StoragePool, new HashSet<ConfigKey<?>>());
         _scopeLevelConfigsMap.put(ConfigKey.Scope.Account, new HashSet<ConfigKey<?>>());
         _scopeLevelConfigsMap.put(ConfigKey.Scope.ImageStore, new HashSet<ConfigKey<?>>());
+        _scopeLevelConfigsMap.put(ConfigKey.Scope.Domain, new HashSet<ConfigKey<?>>());
     }
 
     @Override
diff --git a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java
index 7f1d5b8..4105a61 100644
--- a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java
+++ b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/IntegrationTestConfiguration.java
@@ -140,6 +140,7 @@ import com.cloud.deploy.DeploymentPlanner;
 import com.cloud.deploy.DeploymentPlanningManager;
 import com.cloud.deploy.dao.PlannerHostReservationDaoImpl;
 import com.cloud.domain.dao.DomainDaoImpl;
+import com.cloud.domain.dao.DomainDetailsDaoImpl;
 import com.cloud.event.dao.EventDaoImpl;
 import com.cloud.event.dao.EventJoinDaoImpl;
 import com.cloud.event.dao.UsageEventDaoImpl;
@@ -148,8 +149,8 @@ import com.cloud.host.dao.HostDaoImpl;
 import com.cloud.host.dao.HostDetailsDaoImpl;
 import com.cloud.host.dao.HostTagsDaoImpl;
 import com.cloud.hypervisor.HypervisorGuruManagerImpl;
-import com.cloud.hypervisor.dao.HypervisorCapabilitiesDaoImpl;
 import com.cloud.hypervisor.XenServerGuru;
+import com.cloud.hypervisor.dao.HypervisorCapabilitiesDaoImpl;
 import com.cloud.network.ExternalDeviceUsageManager;
 import com.cloud.network.IpAddress;
 import com.cloud.network.IpAddressManagerImpl;
@@ -169,8 +170,8 @@ import com.cloud.network.as.dao.CounterDaoImpl;
 import com.cloud.network.dao.AccountGuestVlanMapDaoImpl;
 import com.cloud.network.dao.FirewallRulesCidrsDaoImpl;
 import com.cloud.network.dao.FirewallRulesDaoImpl;
-import com.cloud.network.dao.IPAddressDaoImpl;
 import com.cloud.network.dao.IPAddressDao;
+import com.cloud.network.dao.IPAddressDaoImpl;
 import com.cloud.network.dao.LBHealthCheckPolicyDaoImpl;
 import com.cloud.network.dao.LBStickinessPolicyDaoImpl;
 import com.cloud.network.dao.LoadBalancerDaoImpl;
@@ -308,7 +309,7 @@ import com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl;
     ConditionDaoImpl.class, ConfigurationDaoImpl.class, ConfigurationManagerImpl.class, ConfigurationServerImpl.class, ConsoleProxyDaoImpl.class,
     ContrailElementImpl.class, ContrailGuru.class, ContrailManagerImpl.class, CounterDaoImpl.class, DataCenterDaoImpl.class, DataCenterDetailsDaoImpl.class, DataCenterIpAddressDaoImpl.class,
     DataCenterJoinDaoImpl.class, DataCenterLinkLocalIpAddressDaoImpl.class, DataCenterVnetDaoImpl.class, DcDetailsDaoImpl.class, DedicatedResourceDaoImpl.class,
-    DiskOfferingDaoImpl.class, DiskOfferingJoinDaoImpl.class, DomainDaoImpl.class, DomainManagerImpl.class, DomainRouterDaoImpl.class, DomainRouterJoinDaoImpl.class,
+    DiskOfferingDaoImpl.class, DiskOfferingJoinDaoImpl.class, DomainDaoImpl.class, DomainDetailsDaoImpl.class, DomainManagerImpl.class, DomainRouterDaoImpl.class, DomainRouterJoinDaoImpl.class,
     EventDaoImpl.class, EventJoinDaoImpl.class, EventUtils.class, ExtensionRegistry.class, FirewallManagerImpl.class, FirewallRulesCidrsDaoImpl.class,
     FirewallRulesDaoImpl.class, GuestOSCategoryDaoImpl.class, GuestOSDaoImpl.class, HostDaoImpl.class, HostDetailsDaoImpl.class, HostJoinDaoImpl.class,
     HostPodDaoImpl.class, HostTagsDaoImpl.class, HostTransferMapDaoImpl.class, HypervisorCapabilitiesDaoImpl.class, HypervisorGuruManagerImpl.class,
diff --git a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java
index fa93324..37ca2bc 100644
--- a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java
+++ b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java
@@ -317,7 +317,13 @@ public class MockAccountManager extends ManagerBase implements AccountManager {
         return false;
     }
 
-    @Override public boolean moveUser(MoveUserCmd moveUserCmd) {
+    @Override
+    public boolean moveUser(MoveUserCmd moveUserCmd) {
+        return false;
+    }
+
+    @Override
+    public boolean moveUser(long id, Long domainId, long accountId) {
         return false;
     }
 
diff --git a/plugins/user-authenticators/ldap/pom.xml b/plugins/user-authenticators/ldap/pom.xml
index 9f97f08..e2b0ead 100644
--- a/plugins/user-authenticators/ldap/pom.xml
+++ b/plugins/user-authenticators/ldap/pom.xml
@@ -37,9 +37,9 @@
             <configuration>
               <sources>
                 <fileset>
-                  <directory>test/groovy</directory>
+                  <directory>test</directory>
                   <includes>
-                    <include>**/*.groovy</include>
+                    <include>groovy/**/*.groovy</include>
                   </includes>
                 </fileset>
               </sources>
@@ -70,7 +70,8 @@
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
           <includes>
-            <include>**/*Spec*</include>
+            <include>**/*Spec.groovy</include>
+            <include>**/*Test.java</include>
           </includes>
         </configuration>
       </plugin>
@@ -90,6 +91,7 @@
       </plugin>
 
     </plugins>
+    <testSourceDirectory>test</testSourceDirectory>
   </build>
   <dependencies>
     <!-- Mandatory dependencies for using Spock -->
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPConfigCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPConfigCmd.java
index a138e7d..cfef21e 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPConfigCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPConfigCmd.java
@@ -49,7 +49,7 @@ import com.cloud.utils.Pair;
  * @deprecated as of 4.3 use the new api {@link LdapAddConfigurationCmd}
  */
 @Deprecated
-@APICommand(name = "ldapConfig", description = "Configure the LDAP context for this site.", responseObject = LDAPConfigResponse.class, since = "3.0.0",
+@APICommand(name = "ldapConfig", description = "(Deprecated, use addLdapConfiguration) Configure the LDAP context for this site.", responseObject = LDAPConfigResponse.class, since = "3.0.0",
         requestHasSensitiveInfo = true, responseHasSensitiveInfo = false)
 
 public class LDAPConfigCmd extends BaseCmd {
@@ -190,8 +190,8 @@ public class LDAPConfigCmd extends BaseCmd {
 
             if (result.second() > 0) {
                 boolean useSSlConfig = _ldapConfiguration.getSSLStatus();
-                String searchBaseConfig = _ldapConfiguration.getBaseDn();
-                String bindDnConfig = _ldapConfiguration.getBindPrincipal();
+                String searchBaseConfig = _ldapConfiguration.getBaseDn(null);
+                String bindDnConfig = _ldapConfiguration.getBindPrincipal(null);
                 for (LdapConfigurationVO ldapConfigurationVO : result.first()) {
                     responses.add(createLDAPConfigResponse(ldapConfigurationVO.getHostname(), ldapConfigurationVO.getPort(), useSSlConfig, null, searchBaseConfig,
                         bindDnConfig));
@@ -226,7 +226,7 @@ public class LDAPConfigCmd extends BaseCmd {
     }
 
     private boolean updateLDAP() {
-        _ldapManager.addConfiguration(hostname, port);
+        _ldapManager.addConfiguration(hostname, port, null);
 
         /**
          * There is no query filter now. It is derived from ldap.user.object and ldap.search.group.principle
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPRemoveCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPRemoveCmd.java
index eb3729d..0a4dc20 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPRemoveCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LDAPRemoveCmd.java
@@ -35,7 +35,7 @@ import com.cloud.utils.Pair;
  * @deprecated as of 4.3 use the new api {@link LdapDeleteConfigurationCmd}
  */
 @Deprecated
-@APICommand(name = "ldapRemove", description = "Remove the LDAP context for this site.", responseObject = LDAPConfigResponse.class, since = "3.0.1",
+@APICommand(name = "ldapRemove", description = "(Deprecated , use deleteLdapConfiguration) Remove the LDAP context for this site.", responseObject = LDAPConfigResponse.class, since = "3.0.1",
         requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
 public class LDAPRemoveCmd extends BaseCmd {
     public static final Logger s_logger = Logger.getLogger(LDAPRemoveCmd.class.getName());
@@ -60,7 +60,7 @@ public class LDAPRemoveCmd extends BaseCmd {
         LdapListConfigurationCmd listConfigurationCmd = new LdapListConfigurationCmd(_ldapManager);
         Pair<List<? extends LdapConfigurationVO>, Integer> result = _ldapManager.listConfigurations(listConfigurationCmd);
         for (LdapConfigurationVO config : result.first()) {
-            _ldapManager.deleteConfiguration(config.getHostname());
+            _ldapManager.deleteConfiguration(config.getHostname(), 0, null);
         }
         return true;
     }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapAddConfigurationCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapAddConfigurationCmd.java
index 555d1a9..7c59288 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapAddConfigurationCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapAddConfigurationCmd.java
@@ -18,6 +18,8 @@ package org.apache.cloudstack.api.command;
 
 import javax.inject.Inject;
 
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.response.DomainResponse;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.api.APICommand;
@@ -40,12 +42,15 @@ public class LdapAddConfigurationCmd extends BaseCmd {
     @Inject
     private LdapManager _ldapManager;
 
-    @Parameter(name = "hostname", type = CommandType.STRING, required = true, description = "Hostname")
+    @Parameter(name = ApiConstants.HOST_NAME, type = CommandType.STRING, required = true, description = "Hostname")
     private String hostname;
 
-    @Parameter(name = "port", type = CommandType.INTEGER, required = true, description = "Port")
+    @Parameter(name = ApiConstants.PORT, type = CommandType.INTEGER, required = true, description = "Port")
     private int port;
 
+    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = false, entityType = DomainResponse.class, description = "linked domain")
+    private Long domainId;
+
     public LdapAddConfigurationCmd() {
         super();
     }
@@ -58,7 +63,7 @@ public class LdapAddConfigurationCmd extends BaseCmd {
     @Override
     public void execute() throws ServerApiException {
         try {
-            final LdapConfigurationResponse response = _ldapManager.addConfiguration(hostname, port);
+            final LdapConfigurationResponse response = _ldapManager.addConfiguration(hostname, port, domainId);
             response.setObjectName("LdapAddConfiguration");
             response.setResponseName(getCommandName());
             setResponseObject(response);
@@ -86,6 +91,10 @@ public class LdapAddConfigurationCmd extends BaseCmd {
         return port;
     }
 
+    public Long getDomainId() {
+        return domainId;
+    }
+
     public void setHostname(final String hostname) {
         this.hostname = hostname;
     }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java
index d845857..6e69259 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java
@@ -139,7 +139,7 @@ public class LdapCreateAccountCmd extends BaseCmd {
         Long finalDomainId = getDomainId();
         callContext.setEventDetails("Account Name: " + finalAccountName + ", Domain Id:" + finalDomainId);
         try {
-            final LdapUser user = _ldapManager.getUser(username);
+            final LdapUser user = _ldapManager.getUser(username, domainId);
             validateUser(user);
             final UserAccount userAccount = createCloudstackUserAccount(user, finalAccountName, finalDomainId);
             if (userAccount != null) {
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapDeleteConfigurationCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapDeleteConfigurationCmd.java
index 30b37d8..3ffebec 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapDeleteConfigurationCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapDeleteConfigurationCmd.java
@@ -18,6 +18,8 @@ package org.apache.cloudstack.api.command;
 
 import javax.inject.Inject;
 
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.response.DomainResponse;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.api.APICommand;
@@ -40,9 +42,16 @@ public class LdapDeleteConfigurationCmd extends BaseCmd {
     @Inject
     private LdapManager _ldapManager;
 
-    @Parameter(name = "hostname", type = CommandType.STRING, required = true, description = "Hostname")
+
+    @Parameter(name = ApiConstants.HOST_NAME, type = CommandType.STRING, required = true, description = "Hostname")
     private String hostname;
 
+    @Parameter(name = ApiConstants.PORT, type = CommandType.INTEGER, required = false, description = "port")
+    private int port;
+
+    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = false, entityType = DomainResponse.class, description = "linked domain")
+    private Long domainId;
+
     public LdapDeleteConfigurationCmd() {
         super();
     }
@@ -52,10 +61,22 @@ public class LdapDeleteConfigurationCmd extends BaseCmd {
         _ldapManager = ldapManager;
     }
 
+    public String getHostname() {
+        return hostname;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
     @Override
     public void execute() throws ServerApiException {
         try {
-            final LdapConfigurationResponse response = _ldapManager.deleteConfiguration(hostname);
+            final LdapConfigurationResponse response = _ldapManager.deleteConfiguration(this);
             response.setObjectName("LdapDeleteConfiguration");
             response.setResponseName(getCommandName());
             setResponseObject(response);
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
index 9fdd700..564c1d0 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
@@ -142,9 +142,9 @@ public class LdapImportUsersCmd extends BaseListCmd {
         try {
             if (StringUtils.isNotBlank(groupName)) {
 
-                users = _ldapManager.getUsersInGroup(groupName);
+                users = _ldapManager.getUsersInGroup(groupName, domainId);
             } else {
-                users = _ldapManager.getUsers();
+                users = _ldapManager.getUsers(domainId);
             }
         } catch (NoLdapUserMatchingQueryException ex) {
             users = new ArrayList<LdapUser>();
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListConfigurationCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListConfigurationCmd.java
index 050fb36..db6318e 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListConfigurationCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListConfigurationCmd.java
@@ -21,6 +21,8 @@ import java.util.List;
 
 import javax.inject.Inject;
 
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.response.DomainResponse;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.api.APICommand;
@@ -44,12 +46,15 @@ public class LdapListConfigurationCmd extends BaseListCmd {
     @Inject
     private LdapManager _ldapManager;
 
-    @Parameter(name = "hostname", type = CommandType.STRING, required = false, description = "Hostname")
+    @Parameter(name = ApiConstants. HOST_NAME, type = CommandType.STRING, required = false, description = "Hostname")
     private String hostname;
 
-    @Parameter(name = "port", type = CommandType.INTEGER, required = false, description = "Port")
+    @Parameter(name = ApiConstants.PORT, type = CommandType.INTEGER, required = false, description = "Port")
     private int port;
 
+    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = false, entityType = DomainResponse.class, description = "linked domain")
+    private Long domainId;
+
     public LdapListConfigurationCmd() {
         super();
     }
@@ -97,6 +102,10 @@ public class LdapListConfigurationCmd extends BaseListCmd {
         return port;
     }
 
+    public Long getDomainId() {
+        return domainId;
+    }
+
     public void setHostname(final String hostname) {
         this.hostname = hostname;
     }
@@ -104,4 +113,8 @@ public class LdapListConfigurationCmd extends BaseListCmd {
     public void setPort(final int port) {
         this.port = port;
     }
+
+    public void setDomainId(final Long domainId) {
+        this.domainId = domainId;
+    }
 }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListUsersCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListUsersCmd.java
index e655f5f..b2266dc 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListUsersCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListUsersCmd.java
@@ -83,7 +83,7 @@ public class LdapListUsersCmd extends BaseListCmd {
         List<LdapUserResponse> ldapResponses = null;
         final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>();
         try {
-            final List<LdapUser> users = _ldapManager.getUsers();
+            final List<LdapUser> users = _ldapManager.getUsers(null);
             ldapResponses = createLdapUserResponse(users);
         } catch (final NoLdapUserMatchingQueryException ex) {
             ldapResponses = new ArrayList<LdapUserResponse>();
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkAccountToLdapCmd.java
similarity index 57%
copy from plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java
copy to plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkAccountToLdapCmd.java
index 477e80f..52adc66 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkAccountToLdapCmd.java
@@ -18,9 +18,8 @@
  */
 package org.apache.cloudstack.api.command;
 
-import javax.inject.Inject;
-
 import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.user.Account;
 import com.cloud.user.User;
 import com.cloud.user.UserAccount;
 import org.apache.cloudstack.acl.RoleType;
@@ -31,37 +30,39 @@ import org.apache.cloudstack.api.BaseCmd;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.ServerApiException;
 import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.LinkAccountToLdapResponse;
 import org.apache.cloudstack.api.response.LinkDomainToLdapResponse;
 import org.apache.cloudstack.ldap.LdapManager;
 import org.apache.cloudstack.ldap.LdapUser;
 import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
 import org.apache.log4j.Logger;
 
-import com.cloud.user.Account;
-
+import javax.inject.Inject;
 import java.util.UUID;
 
-@APICommand(name = "linkDomainToLdap", description = "link an existing cloudstack domain to group or OU in ldap", responseObject = LinkDomainToLdapResponse.class, since = "4.6.0",
-    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
-public class LinkDomainToLdapCmd extends BaseCmd {
-    public static final Logger s_logger = Logger.getLogger(LinkDomainToLdapCmd.class.getName());
-    private static final String s_name = "linkdomaintoldapresponse";
+@APICommand(name = LinkAccountToLdapCmd.APINAME, description = "link a cloudstack account to a group or OU in ldap", responseObject = LinkDomainToLdapResponse.class, since = "4.11.0",
+    requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin,RoleType.DomainAdmin})
+public class LinkAccountToLdapCmd extends BaseCmd {
+    public static final Logger LOGGER = Logger.getLogger(LinkAccountToLdapCmd.class.getName());
+    public static final String APINAME = "linkAccountToLdap";
 
-    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "The id of the domain which has to be "
-            + "linked to LDAP.")
+    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "The id of the domain that is to contain the linked account.")
     private Long domainId;
 
-    @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, description = "type of the ldap name. GROUP or OU")
+    @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = false, description = "type of the ldap name. GROUP or OU, defaults to GROUP")
     private String type;
 
-    @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the group or OU in LDAP")
-    private String name;
+    @Parameter(name = ApiConstants.LDAP_DOMAIN, type = CommandType.STRING, required = true, description = "name of the group or OU in LDAP")
+    private String ldapDomain;
+
+    @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description = "name of the account, it will be created if it does not exist")
+    private String accountName;
 
     @Parameter(name = ApiConstants.ADMIN, type = CommandType.STRING, required = false, description = "domain admin username in LDAP ")
     private String admin;
 
-    @Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, required = true, description = "Type of the account to auto import. Specify 0 for user and 2 for " +
-        "domain admin")
+    @Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, required = true, description = "Type of the account to auto import. Specify 0 for user and 2 for "
+            + "domain admin")
     private short accountType;
 
     @Inject
@@ -70,33 +71,34 @@ public class LinkDomainToLdapCmd extends BaseCmd {
     @Override
     public void execute() throws ServerApiException {
         try {
-            LinkDomainToLdapResponse response = _ldapManager.linkDomainToLdap(domainId, type, name, accountType);
-            if(admin!=null) {
+            LinkAccountToLdapResponse response = _ldapManager.linkAccountToLdap(this);
+            if (admin != null) {
                 LdapUser ldapUser = null;
                 try {
-                    ldapUser = _ldapManager.getUser(admin, type, name);
+                    ldapUser = _ldapManager.getUser(admin, type, ldapDomain, domainId);
                 } catch (NoLdapUserMatchingQueryException e) {
-                    s_logger.debug("no ldap user matching username " + admin + " in the given group/ou", e);
+                    LOGGER.debug("no ldap user matching username " + admin + " in the given group/ou", e);
                 }
                 if (ldapUser != null && !ldapUser.isDisabled()) {
                     Account account = _accountService.getActiveAccountByName(admin, domainId);
                     if (account == null) {
                         try {
-                            UserAccount userAccount = _accountService.createUserAccount(admin, "", ldapUser.getFirstname(), ldapUser.getLastname(), ldapUser.getEmail(), null,
-                                    admin, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, RoleType.DomainAdmin.getId(), domainId, null, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), User.Source.LDAP);
+                            UserAccount userAccount = _accountService
+                                    .createUserAccount(admin, "", ldapUser.getFirstname(), ldapUser.getLastname(), ldapUser.getEmail(), null, admin, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, RoleType.DomainAdmin.getId(), domainId, null, null, UUID.randomUUID().toString(),
+                                            UUID.randomUUID().toString(), User.Source.LDAP);
                             response.setAdminId(String.valueOf(userAccount.getAccountId()));
-                            s_logger.info("created an account with name " + admin + " in the given domain " + domainId);
+                            LOGGER.info("created an account with name " + admin + " in the given domain " + domainId);
                         } catch (Exception e) {
-                            s_logger.info("an exception occurred while creating account with name " + admin +" in domain " + domainId, e);
+                            LOGGER.info("an exception occurred while creating account with name " + admin + " in domain " + domainId, e);
                         }
                     } else {
-                        s_logger.debug("an account with name " + admin + " already exists in the domain " + domainId);
+                        LOGGER.debug("an account with name " + admin + " already exists in the domain " + domainId);
                     }
                 } else {
-                    s_logger.debug("ldap user with username "+admin+" is disabled in the given group/ou");
+                    LOGGER.debug("ldap user with username " + admin + " is disabled in the given group/ou");
                 }
             }
-            response.setObjectName("LinkDomainToLdap");
+            response.setObjectName(APINAME);
             response.setResponseName(getCommandName());
             setResponseObject(response);
         } catch (final InvalidParameterValueException e) {
@@ -106,11 +108,35 @@ public class LinkDomainToLdapCmd extends BaseCmd {
 
     @Override
     public String getCommandName() {
-        return s_name;
+        return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
     }
 
     @Override
     public long getEntityOwnerId() {
         return Account.ACCOUNT_ID_SYSTEM;
     }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getLdapDomain() {
+        return ldapDomain;
+    }
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public String getAdmin() {
+        return admin;
+    }
+
+    public short getAccountType() {
+        return accountType;
+    }
 }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java
index 477e80f..0014095 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java
@@ -54,6 +54,10 @@ public class LinkDomainToLdapCmd extends BaseCmd {
     @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, description = "type of the ldap name. GROUP or OU")
     private String type;
 
+    @Parameter(name = ApiConstants.LDAP_DOMAIN, type = CommandType.STRING, required = true, description = "name of the group or OU in LDAP")
+    private String ldapDomain;
+
+    @Deprecated
     @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the group or OU in LDAP")
     private String name;
 
@@ -67,14 +71,35 @@ public class LinkDomainToLdapCmd extends BaseCmd {
     @Inject
     private LdapManager _ldapManager;
 
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getLdapDomain() {
+        return ldapDomain == null ? name : ldapDomain;
+    }
+
+    public String getAdmin() {
+        return admin;
+    }
+
+    public short getAccountType() {
+        return accountType;
+    }
+
+
     @Override
     public void execute() throws ServerApiException {
         try {
-            LinkDomainToLdapResponse response = _ldapManager.linkDomainToLdap(domainId, type, name, accountType);
+            LinkDomainToLdapResponse response = _ldapManager.linkDomainToLdap(this);
             if(admin!=null) {
                 LdapUser ldapUser = null;
                 try {
-                    ldapUser = _ldapManager.getUser(admin, type, name);
+                    ldapUser = _ldapManager.getUser(admin, type, getLdapDomain(), domainId);
                 } catch (NoLdapUserMatchingQueryException e) {
                     s_logger.debug("no ldap user matching username " + admin + " in the given group/ou", e);
                 }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapConfigurationResponse.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapConfigurationResponse.java
index a4e4782..c6d2bf3 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapConfigurationResponse.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapConfigurationResponse.java
@@ -18,31 +18,44 @@ package org.apache.cloudstack.api.response;
 
 import com.google.gson.annotations.SerializedName;
 
+import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.BaseResponse;
 
 import com.cloud.serializer.Param;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.ldap.LdapConfiguration;
 
+@EntityReference(value = LdapConfiguration.class)
 public class LdapConfigurationResponse extends BaseResponse {
-    @SerializedName("hostname")
-    @Param(description = "hostname")
+    @SerializedName(ApiConstants.HOST_NAME)
+    @Param(description = "name of the host running the ldap server")
     private String hostname;
 
-    @SerializedName("port")
-    @Param(description = "port")
+    @SerializedName(ApiConstants.PORT)
+    @Param(description = "port teh ldap server is running on")
     private int port;
 
+    @SerializedName(ApiConstants.DOMAIN_ID)
+    @Param(description = "linked domain")
+    private String domainId;
+
     public LdapConfigurationResponse() {
         super();
     }
 
     public LdapConfigurationResponse(final String hostname) {
         super();
-        this.hostname = hostname;
+        setHostname(hostname);
     }
 
     public LdapConfigurationResponse(final String hostname, final int port) {
-        this.hostname = hostname;
-        this.port = port;
+        this(hostname);
+        setPort(port);
+    }
+
+    public LdapConfigurationResponse(final String hostname, final int port, final String domainId) {
+        this(hostname, port);
+        setDomainId(domainId);
     }
 
     public String getHostname() {
@@ -60,4 +73,12 @@ public class LdapConfigurationResponse extends BaseResponse {
     public void setPort(final int port) {
         this.port = port;
     }
+
+    public String getDomainId() {
+        return domainId;
+    }
+
+    public void setDomainId(String domainId) {
+        this.domainId = domainId;
+    }
 }
\ No newline at end of file
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LinkDomainToLdapResponse.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LinkAccountToLdapResponse.java
similarity index 81%
copy from plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LinkDomainToLdapResponse.java
copy to plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LinkAccountToLdapResponse.java
index 050eb6c..23456e7 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LinkDomainToLdapResponse.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LinkAccountToLdapResponse.java
@@ -23,17 +23,12 @@ import com.google.gson.annotations.SerializedName;
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.BaseResponse;
 
-public class LinkDomainToLdapResponse extends BaseResponse {
+public class LinkAccountToLdapResponse extends BaseResponse {
 
     @SerializedName(ApiConstants.DOMAIN_ID)
     @Param(description = "id of the Domain which is linked to LDAP")
     private String domainId;
 
-    @Deprecated
-    @SerializedName(ApiConstants.NAME)
-    @Param(description = "name of the group or OU in LDAP which is linked to the domain")
-    private String name;
-
     @SerializedName(ApiConstants.LDAP_DOMAIN)
     @Param(description = "name of the group or OU in LDAP which is linked to the domain")
     private String ldapDomain;
@@ -50,12 +45,18 @@ public class LinkDomainToLdapResponse extends BaseResponse {
     @Param(description = "Domain Admin accountId that is created")
     private String adminId;
 
-    public LinkDomainToLdapResponse(String domainId, String type, String ldapDomain, short accountType) {
+    @SerializedName(ApiConstants.ACCOUNT)
+    @Param(description = "name of the account")
+    private String accountName;
+
+
+    public LinkAccountToLdapResponse(String domainId, String type, String ldapDomain, short accountType, String adminId, String accountName) {
         this.domainId = domainId;
-        this.name = ldapDomain;
-        this.ldapDomain = ldapDomain;
         this.type = type;
+        this.ldapDomain = ldapDomain;
         this.accountType = accountType;
+        this.adminId = adminId;
+        this.accountName = accountName;
     }
 
     public String getDomainId() {
@@ -63,12 +64,7 @@ public class LinkDomainToLdapResponse extends BaseResponse {
     }
 
     public String getLdapDomain() {
-        return ldapDomain == null ? name : ldapDomain;
-    }
-
-    @Deprecated
-    public String getName() {
-        return ldapDomain == null ? name : ldapDomain;
+        return ldapDomain;
     }
 
     public String getType() {
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LinkDomainToLdapResponse.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LinkDomainToLdapResponse.java
index 050eb6c..d6d4b55 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LinkDomainToLdapResponse.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LinkDomainToLdapResponse.java
@@ -66,11 +66,6 @@ public class LinkDomainToLdapResponse extends BaseResponse {
         return ldapDomain == null ? name : ldapDomain;
     }
 
-    @Deprecated
-    public String getName() {
-        return ldapDomain == null ? name : ldapDomain;
-    }
-
     public String getType() {
         return type;
     }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/ADLdapUserManagerImpl.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/ADLdapUserManagerImpl.java
index 0df638a..e844df5 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/ADLdapUserManagerImpl.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/ADLdapUserManagerImpl.java
@@ -36,38 +36,38 @@ public class ADLdapUserManagerImpl extends OpenLdapUserManagerImpl implements Ld
     private static final String MICROSOFT_AD_MEMBERS_FILTER = "memberOf";
 
     @Override
-    public List<LdapUser> getUsersInGroup(String groupName, LdapContext context) throws NamingException {
+    public List<LdapUser> getUsersInGroup(String groupName, LdapContext context, Long domainId) throws NamingException {
         if (StringUtils.isBlank(groupName)) {
             throw new IllegalArgumentException("ldap group name cannot be blank");
         }
 
-        String basedn = _ldapConfiguration.getBaseDn();
+        String basedn = _ldapConfiguration.getBaseDn(domainId);
         if (StringUtils.isBlank(basedn)) {
             throw new IllegalArgumentException("ldap basedn is not configured");
         }
 
         final SearchControls searchControls = new SearchControls();
         searchControls.setSearchScope(_ldapConfiguration.getScope());
-        searchControls.setReturningAttributes(_ldapConfiguration.getReturnAttributes());
+        searchControls.setReturningAttributes(_ldapConfiguration.getReturnAttributes(domainId));
 
-        NamingEnumeration<SearchResult> results = context.search(basedn, generateADGroupSearchFilter(groupName), searchControls);
+        NamingEnumeration<SearchResult> results = context.search(basedn, generateADGroupSearchFilter(groupName, domainId), searchControls);
         final List<LdapUser> users = new ArrayList<LdapUser>();
         while (results.hasMoreElements()) {
             final SearchResult result = results.nextElement();
-            users.add(createUser(result));
+            users.add(createUser(result, domainId));
         }
         return users;
     }
 
-    private String generateADGroupSearchFilter(String groupName) {
+    private String generateADGroupSearchFilter(String groupName, Long domainId) {
         final StringBuilder userObjectFilter = new StringBuilder();
         userObjectFilter.append("(objectClass=");
-        userObjectFilter.append(_ldapConfiguration.getUserObject());
+        userObjectFilter.append(_ldapConfiguration.getUserObject(domainId));
         userObjectFilter.append(")");
 
         final StringBuilder memberOfFilter = new StringBuilder();
-        String groupCnName =  _ldapConfiguration.getCommonNameAttribute() + "=" +groupName + "," +  _ldapConfiguration.getBaseDn();
-        memberOfFilter.append("(").append(getMemberOfAttribute()).append("=");
+        String groupCnName =  _ldapConfiguration.getCommonNameAttribute() + "=" +groupName + "," +  _ldapConfiguration.getBaseDn(domainId);
+        memberOfFilter.append("(").append(getMemberOfAttribute(domainId)).append("=");
         memberOfFilter.append(groupCnName);
         memberOfFilter.append(")");
 
@@ -94,8 +94,8 @@ public class ADLdapUserManagerImpl extends OpenLdapUserManagerImpl implements Ld
         return isDisabledUser;
     }
 
-    protected String getMemberOfAttribute() {
-        if(_ldapConfiguration.isNestedGroupsEnabled()) {
+    protected String getMemberOfAttribute(final Long domainId) {
+        if(_ldapConfiguration.isNestedGroupsEnabled(domainId)) {
             return MICROSOFT_AD_NESTED_MEMBERS_FILTER;
         } else {
             return MICROSOFT_AD_MEMBERS_FILTER;
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java
index add39c5..cd4ed3d 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java
@@ -16,6 +16,8 @@
 // under the License.
 package org.apache.cloudstack.ldap;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
@@ -56,60 +58,181 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
 
     @Override
     public Pair<Boolean, ActionOnFailedAuthentication> authenticate(final String username, final String password, final Long domainId, final Map<String, Object[]> requestParameters) {
+        Pair<Boolean, ActionOnFailedAuthentication> rc = new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
 
+        // TODO not allowing an empty password is a policy we shouldn't decide on. A private cloud may well want to allow this.
         if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
             s_logger.debug("Username or Password cannot be empty");
-            return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
+            return rc;
         }
 
-        boolean result = false;
-        ActionOnFailedAuthentication action = null;
-
         if (_ldapManager.isLdapEnabled()) {
             final UserAccount user = _userAccountDao.getUserAccount(username, domainId);
-            LdapTrustMapVO ldapTrustMapVO = _ldapManager.getDomainLinkedToLdap(domainId);
-            if(ldapTrustMapVO != null) {
-                try {
-                    LdapUser ldapUser = _ldapManager.getUser(username, ldapTrustMapVO.getType().toString(), ldapTrustMapVO.getName());
-                    if(!ldapUser.isDisabled()) {
-                        result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password);
-                        if(result) {
-                            if(user == null) {
-                                // import user to cloudstack
-                                createCloudStackUserAccount(ldapUser, domainId, ldapTrustMapVO.getAccountType());
-                            } else {
-                                enableUserInCloudStack(user);
-                            }
-                        }
-                    } else {
-                        //disable user in cloudstack
-                        disableUserInCloudStack(user);
-                    }
-                } catch (NoLdapUserMatchingQueryException e) {
-                    s_logger.debug(e.getMessage());
+            List<LdapTrustMapVO> ldapTrustMapVOs = _ldapManager.getDomainLinkage(domainId);
+            if(ldapTrustMapVOs != null && ldapTrustMapVOs.size() > 0) {
+                if(ldapTrustMapVOs.size() == 1 && ldapTrustMapVOs.get(0).getAccountId() == 0) {
+                    // We have a single mapping of a domain to an ldap group or ou
+                    return authenticate(username, password, domainId, user, ldapTrustMapVOs.get(0));
+                } else {
+                    // we are dealing with mapping of accounts in a domain to ldap groups
+                    return authenticate(username, password, domainId, user, ldapTrustMapVOs);
                 }
-
             } else {
                 //domain is not linked to ldap follow normal authentication
-                if(user != null ) {
-                    try {
-                        LdapUser ldapUser = _ldapManager.getUser(username);
-                        if(!ldapUser.isDisabled()) {
-                            result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password);
-                        } else {
-                            s_logger.debug("user with principal "+ ldapUser.getPrincipal() + " is disabled in ldap");
-                        }
-                    } catch (NoLdapUserMatchingQueryException e) {
-                        s_logger.debug(e.getMessage());
+                return authenticate(username, password, domainId, user);
+            }
+        }
+
+        return rc;
+    }
+
+    /**
+     * checks if the user exists in ldap and create in cloudstack if needed.
+     *
+     * @param username login id
+     * @param password pass phrase
+     * @param domainId domain the user is trying to log on to
+     * @param userAccount cloudstack user object
+     * @param ldapTrustMapVOs the trust mappings of accounts in the domain to ldap groups
+     * @return false if the ldap user object does not exist, is not mapped to an account, is mapped to multiple accounts or if authenitication fails
+     */
+    private Pair<Boolean, ActionOnFailedAuthentication> authenticate(String username, String password, Long domainId, UserAccount userAccount, List<LdapTrustMapVO> ldapTrustMapVOs) {
+        Pair<Boolean, ActionOnFailedAuthentication> rc = new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
+        try {
+            LdapUser ldapUser = _ldapManager.getUser(username, domainId);
+            List<String> memberships = ldapUser.getMemberships();
+            List<String> mappedGroups = getMappedGroups(ldapTrustMapVOs);
+            mappedGroups.retainAll(memberships);
+            // check membership, there must be only one match in this domain
+            if(ldapUser.isDisabled()) {
+                logAndDisable(userAccount, "attempt to log on using disabled ldap user " + userAccount.getUsername(), false);
+            } else if(mappedGroups.size() > 1) {
+                logAndDisable(userAccount, "user '" + username + "' is mapped to more then one account in domain and will be disabled.", false);
+            } else if(mappedGroups.size() < 1) {
+                logAndDisable(userAccount, "user '" + username + "' is not mapped to an account in domain and will be removed.", true);
+            } else {
+                // a valid ldap configured user exists
+                LdapTrustMapVO mapping = _ldapManager.getLinkedLdapGroup(domainId,mappedGroups.get(0));
+                // we could now assert that ldapTrustMapVOs.contains(mapping);
+                // createUser in Account can only be done by account name not by account id
+                String accountName = _accountManager.getAccount(mapping.getAccountId()).getAccountName();
+                rc.first(_ldapManager.canAuthenticate(ldapUser.getPrincipal(), password, domainId));
+                // for security reasons we keep processing on faulty login attempt to not give a way information on userid existence
+                if (userAccount == null) {
+                    // new user that is in ldap; authenticate and create
+                    User user = _accountManager.createUser(username, "", ldapUser.getFirstname(), ldapUser.getLastname(), ldapUser.getEmail(), null, accountName,
+                            domainId, UUID.randomUUID().toString(), User.Source.LDAP);
+                    /* expected error conditions:
+                     *
+                     * caught in APIServlet: CloudRuntimeException("The domain " + domainId + " does not exist; unable to create user");
+                     * caught in APIServlet: CloudRuntimeException("The user cannot be created as domain " + domain.getName() + " is being deleted");
+                     * would have been thrown above: InvalidParameterValueException("Unable to find account " + accountName + " in domain id=" + domainId + " to create user");
+                     * we are system user: PermissionDeniedException("Account id : " + account.getId() + " is a system account, can't add a user to it");
+                     * serious and must be thrown: CloudRuntimeException("The user " + userName + " already exists in domain " + domainId);
+                     * fatal system error and must be thrown: CloudRuntimeException("Failed to encode password");
+                     */
+                    userAccount = _accountManager.getUserAccountById(user.getId());
+                } else {
+                    // not a new user, check if mapped group has changed
+                    if(userAccount.getAccountId() != mapping.getAccountId()) {
+                        _accountManager.moveUser(userAccount.getId(),userAccount.getDomainId(),mapping.getAccountId());
                     }
+                    // else { the user hasn't changed in ldap, the ldap group stayed the same, hurray, pass, fun thou self a lot of fun }
                 }
             }
-            if (!result && user != null) {
-                action = ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT;
+        } catch (NoLdapUserMatchingQueryException e) {
+            s_logger.debug(e.getMessage());
+            disableUserInCloudStack(userAccount);
+        }
+
+        return rc;
+    }
+
+    private void logAndDisable(UserAccount userAccount, String msg, boolean remove) {
+        if (s_logger.isInfoEnabled()) {
+            s_logger.info(msg);
+        }
+        if(remove) {
+            removeUserInCloudStack(userAccount);
+        } else {
+            disableUserInCloudStack(userAccount);
+        }
+    }
+
+    private List<String> getMappedGroups(List<LdapTrustMapVO> ldapTrustMapVOs) {
+        List<String> groups = new ArrayList<>();
+        for (LdapTrustMapVO vo : ldapTrustMapVOs) {
+            groups.add(vo.getName());
+        }
+        return groups;
+    }
+
+    /**
+     * checks if the user exists in ldap and create in cloudstack if needed
+     * @param username login id
+     * @param password pass phrase
+     * @param domainId domain the user is trying to log on to
+     * @param user cloudstack user object
+     * @param ldapTrustMapVO the trust mapping for the domain to the ldap group
+     * @return false if the ldap user object does not exist or authenitication fails
+     */
+    private Pair<Boolean, ActionOnFailedAuthentication> authenticate(String username, String password, Long domainId, UserAccount user, LdapTrustMapVO ldapTrustMapVO) {
+        Pair<Boolean, ActionOnFailedAuthentication> rc = new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
+        try {
+            LdapUser ldapUser = _ldapManager.getUser(username, ldapTrustMapVO.getType().toString(), ldapTrustMapVO.getName(), domainId);
+            final short accountType = ldapTrustMapVO.getAccountType();
+            processLdapUser(password, domainId, user, rc, ldapUser, accountType);
+        } catch (NoLdapUserMatchingQueryException e) {
+            s_logger.debug(e.getMessage());
+        }
+        return rc;
+    }
+
+    private void processLdapUser(String password, Long domainId, UserAccount user, Pair<Boolean, ActionOnFailedAuthentication> rc, LdapUser ldapUser, short accountType) {
+        if(!ldapUser.isDisabled()) {
+            rc.first(_ldapManager.canAuthenticate(ldapUser.getPrincipal(), password, domainId));
+            if(rc.first()) {
+                if(user == null) {
+                    // import user to cloudstack
+                    createCloudStackUserAccount(ldapUser, domainId, accountType);
+                } else {
+                    enableUserInCloudStack(user);
+                }
+            } else if(user != null) {
+                rc.second(ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);
             }
+        } else {
+            //disable user in cloudstack
+            disableUserInCloudStack(user);
         }
+    }
+
+    /**
+     * checks if the user is configured both in ldap and in cloudstack.
+     * @param username login id
+     * @param password pass phrase
+     * @param domainId domain the user is trying to log on to
+     * @param user cloudstack user object
+     * @return false if either user object does not exist or authenitication fails
+     */
+    private Pair<Boolean, ActionOnFailedAuthentication> authenticate(String username, String password, Long domainId, UserAccount user) {
+        boolean result = false;
 
-        return new Pair<Boolean, ActionOnFailedAuthentication>(result, action);
+        if(user != null ) {
+            try {
+                LdapUser ldapUser = _ldapManager.getUser(username, domainId);
+                if(!ldapUser.isDisabled()) {
+                    result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password, domainId);
+                } else {
+                    s_logger.debug("user with principal "+ ldapUser.getPrincipal() + " is disabled in ldap");
+                }
+            } catch (NoLdapUserMatchingQueryException e) {
+                s_logger.debug(e.getMessage());
+            }
+        }
+        return (!result && user != null) ?
+                new Pair<Boolean, ActionOnFailedAuthentication>(false, ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT):
+                new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
     }
 
     private void enableUserInCloudStack(UserAccount user) {
@@ -131,6 +254,12 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
         }
     }
 
+    private void removeUserInCloudStack(UserAccount user) {
+        if (user != null) {
+            _accountManager.disableUser(user.getId());
+        }
+    }
+
     @Override
     public String encode(final String password) {
         return password;
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java
index 56b39a8..22f8abc 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java
@@ -31,75 +31,215 @@ import org.apache.cloudstack.ldap.dao.LdapConfigurationDao;
 public class LdapConfiguration implements Configurable{
     private final static String factory = "com.sun.jndi.ldap.LdapCtxFactory";
 
-    private static final ConfigKey<Long> ldapReadTimeout = new ConfigKey<Long>(Long.class, "ldap.read.timeout", "Advanced", "1000",
-        "LDAP connection Timeout in milli sec", true, ConfigKey.Scope.Global, 1l);
-
-    private static final ConfigKey<Integer> ldapPageSize = new ConfigKey<Integer>(Integer.class, "ldap.request.page.size", "Advanced", "1000",
-                                                                               "page size sent to ldap server on each request to get user", true, ConfigKey.Scope.Global, 1);
-    private static final ConfigKey<String> ldapProvider = new ConfigKey<String>(String.class, "ldap.provider", "Advanced", "openldap", "ldap provider ex:openldap, microsoftad",
-                                                                                true, ConfigKey.Scope.Global, null);
-
-    private static final ConfigKey<Boolean> ldapEnableNestedGroups = new ConfigKey<Boolean>(Boolean.class, "ldap.nested.groups.enable", "Advanced", "true",
-                                                                                            "if true, nested groups will also be queried", true, ConfigKey.Scope.Global, null);
+    private static final ConfigKey<Long> ldapReadTimeout = new ConfigKey<Long>(
+            Long.class,
+            "ldap.read.timeout",
+            "Advanced",
+            "1000",
+            "LDAP connection Timeout in milli sec",
+            true,
+            ConfigKey.Scope.Domain,
+            1l);
+
+    private static final ConfigKey<Integer> ldapPageSize = new ConfigKey<Integer>(
+            Integer.class,
+            "ldap.request.page.size",
+            "Advanced",
+            "1000",
+            "page size sent to ldap server on each request to get user",
+            true,
+            ConfigKey.Scope.Domain,
+            1);
+
+    private static final ConfigKey<Boolean> ldapEnableNestedGroups = new ConfigKey<Boolean>(
+            "Advanced",
+            Boolean.class,
+            "ldap.nested.groups.enable",
+            "true",
+            "if true, nested groups will also be queried",
+            true,
+            ConfigKey.Scope.Domain);
+
+    private static final ConfigKey<String> ldapMemberOfAttribute = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.user.memberof.attribute",
+            "memberof",
+            "the reverse membership attibute for group members",
+            true,
+            ConfigKey.Scope.Domain);
+
+    private static final ConfigKey<String> ldapProvider = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.provider",
+            "openldap",
+            "ldap provider ex:openldap, microsoftad",
+            true,
+            ConfigKey.Scope.Domain);
+
+    private static final ConfigKey<String> ldapBaseDn = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.basedn",
+            null,
+            "Sets the basedn for LDAP",
+            true,
+            ConfigKey.Scope.Domain);
+
+    private static final ConfigKey<String> ldapBindPassword = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.bind.password",
+            null,
+            "Sets the bind password for LDAP",
+            true,
+            ConfigKey.Scope.Domain);
+    private static final ConfigKey<String> ldapBindPrincipal = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.bind.principal",
+            null,
+            "Sets the bind principal for LDAP",
+            true,
+            ConfigKey.Scope.Domain);
+    private static final ConfigKey<String> ldapEmailAttribute = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.email.attribute",
+            "mail",
+            "Sets the email attribute used within LDAP",
+            true,
+            ConfigKey.Scope.Domain);
+    private static final ConfigKey<String> ldapFirstnameAttribute = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.firstname.attribute",
+            "givenname",
+            "Sets the firstname attribute used within LDAP",
+            true,
+            ConfigKey.Scope.Domain);
+    private static final ConfigKey<String> ldapLastnameAttribute = new ConfigKey<String>(
+            "Advanced",
+            String.class, "ldap.lastname.attribute",
+            "sn",
+            "Sets the lastname attribute used within LDAP",
+            true,
+            ConfigKey.Scope.Domain);
+    private static final ConfigKey<String> ldapUsernameAttribute = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.username.attribute",
+            "uid",
+            "Sets the username attribute used within LDAP",
+            true,
+            ConfigKey.Scope.Domain);
+    private static final ConfigKey<String> ldapUserObject = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.user.object",
+            "inetOrgPerson",
+            "Sets the object type of users within LDAP",
+            true,
+            ConfigKey.Scope.Domain);
+    private static final ConfigKey<String> ldapSearchGroupPrinciple = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.search.group.principle",
+            null,
+            "Sets the principle of the group that users must be a member of",
+            true,
+            ConfigKey.Scope.Domain);
+    private static final ConfigKey<String> ldapGroupObject = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.group.object",
+            "groupOfUniqueNames",
+            "Sets the object type of groups within LDAP",
+            true,
+            ConfigKey.Scope.Domain);
+    private static final ConfigKey<String> ldapGroupUniqueMemberAttribute = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.group.user.uniquemember",
+            "uniquemember",
+            "Sets the attribute for uniquemembers within a group",
+            true,
+            ConfigKey.Scope.Domain);
+
+    private static final ConfigKey<String> ldapTrustStore = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.truststore",
+            null,
+            "Sets the path to the truststore to use for SSL",
+            true,
+            ConfigKey.Scope.Domain);
+    private static final ConfigKey<String> ldapTrustStorePassword = new ConfigKey<String>(
+            "Advanced",
+            String.class,
+            "ldap.truststore.password",
+            null,
+            "Sets the password for the truststore",
+            true,
+            ConfigKey.Scope.Domain);
 
     private final static int scope = SearchControls.SUBTREE_SCOPE;
 
     @Inject
-    private ConfigurationDao _configDao;
-
-    @Inject
     private LdapConfigurationDao _ldapConfigurationDao;
 
     public LdapConfiguration() {
     }
 
+    public LdapConfiguration(final LdapConfigurationDao ldapConfigurationDao) {
+        _ldapConfigurationDao = ldapConfigurationDao;
+    }
+
+    @Deprecated
     public LdapConfiguration(final ConfigurationDao configDao, final LdapConfigurationDao ldapConfigurationDao) {
-        _configDao = configDao;
         _ldapConfigurationDao = ldapConfigurationDao;
     }
 
-    public String getAuthentication() {
-        if ((getBindPrincipal() == null) && (getBindPassword() == null)) {
+    public String getAuthentication(final Long domainId) {
+        if ((getBindPrincipal(domainId) == null) && (getBindPassword(domainId) == null)) {
             return "none";
         } else {
             return "simple";
         }
     }
 
-    public String getBaseDn() {
-        return _configDao.getValue("ldap.basedn");
+    public String getBaseDn(final Long domainId) {
+        return ldapBaseDn.valueIn(domainId);
     }
 
-    public String getBindPassword() {
-        return _configDao.getValue("ldap.bind.password");
+    public String getBindPassword(final Long domainId) {
+        return ldapBindPassword.valueIn(domainId);
     }
 
-    public String getBindPrincipal() {
-        return _configDao.getValue("ldap.bind.principal");
+    public String getBindPrincipal(final Long domainId) {
+        return ldapBindPrincipal.valueIn(domainId);
     }
 
-    public String getEmailAttribute() {
-        final String emailAttribute = _configDao.getValue("ldap.email.attribute");
-        return emailAttribute == null ? "mail" : emailAttribute;
+    public String getEmailAttribute(final Long domainId) {
+        return ldapEmailAttribute.valueIn(domainId);
     }
 
     public String getFactory() {
         return factory;
     }
 
-    public String getFirstnameAttribute() {
-        final String firstnameAttribute = _configDao.getValue("ldap.firstname.attribute");
-        return firstnameAttribute == null ? "givenname" : firstnameAttribute;
+    public String getFirstnameAttribute(final Long domainId) {
+        return ldapFirstnameAttribute.valueIn(domainId);
     }
 
-    public String getLastnameAttribute() {
-        final String lastnameAttribute = _configDao.getValue("ldap.lastname.attribute");
-        return lastnameAttribute == null ? "sn" : lastnameAttribute;
+    public String getLastnameAttribute(final Long domainId) {
+        return ldapLastnameAttribute.valueIn(domainId);
     }
 
-    public String getProviderUrl() {
+    public String getProviderUrl(final Long domainId) {
         final String protocol = getSSLStatus() == true ? "ldaps://" : "ldap://";
-        final Pair<List<LdapConfigurationVO>, Integer> result = _ldapConfigurationDao.searchConfigurations(null, 0);
+        final Pair<List<LdapConfigurationVO>, Integer> result = _ldapConfigurationDao.searchConfigurations(null, 0, domainId);
         final StringBuilder providerUrls = new StringBuilder();
         String delim = "";
         for (final LdapConfigurationVO resource : result.first()) {
@@ -110,17 +250,24 @@ public class LdapConfiguration implements Configurable{
         return providerUrls.toString();
     }
 
-    public String[] getReturnAttributes() {
-        return new String[] {getUsernameAttribute(), getEmailAttribute(), getFirstnameAttribute(), getLastnameAttribute(), getCommonNameAttribute(),
-                getUserAccountControlAttribute()};
+    public String[] getReturnAttributes(final Long domainId) {
+        return new String[] {
+                getUsernameAttribute(domainId),
+                getEmailAttribute(domainId),
+                getFirstnameAttribute(domainId),
+                getLastnameAttribute(domainId),
+                getCommonNameAttribute(),
+                getUserAccountControlAttribute(),
+                getUserMemberOfAttribute(domainId)
+        };
     }
 
     public int getScope() {
         return scope;
     }
 
-    public String getSearchGroupPrinciple() {
-        return _configDao.getValue("ldap.search.group.principle");
+    public String getSearchGroupPrinciple(final Long domainId) {
+        return ldapSearchGroupPrinciple.valueIn(domainId);
     }
 
     public boolean getSSLStatus() {
@@ -132,53 +279,51 @@ public class LdapConfiguration implements Configurable{
     }
 
     public String getTrustStore() {
-        return _configDao.getValue("ldap.truststore");
+        return ldapTrustStore.value();
     }
 
     public String getTrustStorePassword() {
-        return _configDao.getValue("ldap.truststore.password");
+        return ldapTrustStorePassword.value();
     }
 
-    public String getUsernameAttribute() {
-        final String usernameAttribute = _configDao.getValue("ldap.username.attribute");
-        return usernameAttribute == null ? "uid" : usernameAttribute;
+    public String getUsernameAttribute(final Long domainId) {
+        return ldapUsernameAttribute.valueIn(domainId);
     }
 
-    public String getUserObject() {
-        final String userObject = _configDao.getValue("ldap.user.object");
-        return userObject == null ? "inetOrgPerson" : userObject;
+    public String getUserObject(final Long domainId) {
+        return ldapUserObject.valueIn(domainId);
     }
 
-    public String getGroupObject() {
-        final String groupObject = _configDao.getValue("ldap.group.object");
-        return groupObject == null ? "groupOfUniqueNames" : groupObject;
+    public String getGroupObject(final Long domainId) {
+        return ldapGroupObject.valueIn(domainId);
     }
 
-    public String getGroupUniqueMemeberAttribute() {
-        final String uniqueMemberAttribute = _configDao.getValue("ldap.group.user.uniquemember");
-        return uniqueMemberAttribute == null ? "uniquemember" : uniqueMemberAttribute;
+    public String getGroupUniqueMemberAttribute(final Long domainId) {
+        return ldapGroupUniqueMemberAttribute.valueIn(domainId);
     }
 
+    // TODO remove hard-coding
     public String getCommonNameAttribute() {
         return "cn";
     }
 
+    // TODO remove hard-coding
     public String getUserAccountControlAttribute() {
         return "userAccountControl";
     }
 
-    public Long getReadTimeout() {
-        return ldapReadTimeout.value();
+    public Long getReadTimeout(final Long domainId) {
+        return ldapReadTimeout.valueIn(domainId);
     }
 
-    public Integer getLdapPageSize() {
-        return ldapPageSize.value();
+    public Integer getLdapPageSize(final Long domainId) {
+        return ldapPageSize.valueIn(domainId);
     }
 
-    public LdapUserManager.Provider getLdapProvider() {
+    public LdapUserManager.Provider getLdapProvider(final Long domainId) {
         LdapUserManager.Provider provider;
         try {
-            provider = LdapUserManager.Provider.valueOf(ldapProvider.value().toUpperCase());
+            provider = LdapUserManager.Provider.valueOf(ldapProvider.valueIn(domainId).toUpperCase());
         } catch (IllegalArgumentException ex) {
             //openldap is the default
             provider = LdapUserManager.Provider.OPENLDAP;
@@ -186,8 +331,12 @@ public class LdapConfiguration implements Configurable{
         return provider;
     }
 
-    public boolean isNestedGroupsEnabled() {
-        return ldapEnableNestedGroups.value();
+    public boolean isNestedGroupsEnabled(final Long domainId) {
+        return ldapEnableNestedGroups.valueIn(domainId);
+    }
+
+    public static String getUserMemberOfAttribute(final Long domainId) {
+        return ldapMemberOfAttribute.valueIn(domainId);
     }
 
     @Override
@@ -197,6 +346,25 @@ public class LdapConfiguration implements Configurable{
 
     @Override
     public ConfigKey<?>[] getConfigKeys() {
-        return new ConfigKey<?>[] {ldapReadTimeout, ldapPageSize, ldapProvider, ldapEnableNestedGroups};
+        return new ConfigKey<?>[]{
+                ldapReadTimeout,
+                ldapPageSize,
+                ldapProvider,
+                ldapEnableNestedGroups,
+                ldapBaseDn,
+                ldapBindPassword,
+                ldapBindPrincipal,
+                ldapEmailAttribute,
+                ldapFirstnameAttribute,
+                ldapLastnameAttribute,
+                ldapUsernameAttribute,
+                ldapUserObject,
+                ldapSearchGroupPrinciple,
+                ldapGroupObject,
+                ldapGroupUniqueMemberAttribute,
+                ldapTrustStore,
+                ldapTrustStorePassword,
+                ldapMemberOfAttribute
+        };
     }
-}
\ No newline at end of file
+}
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java
index 488e7f4..e7db886 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java
@@ -39,12 +39,16 @@ public class LdapConfigurationVO implements InternalIdentity {
     @Column(name = "port")
     private int port;
 
+    @Column(name = "domain_id")
+    private Long domainId;
+
     public LdapConfigurationVO() {
     }
 
-    public LdapConfigurationVO(final String hostname, final int port) {
+    public LdapConfigurationVO(final String hostname, final int port, final Long domainId) {
         this.hostname = hostname;
         this.port = port;
+        this.domainId = domainId;
     }
 
     public String getHostname() {
@@ -60,6 +64,10 @@ public class LdapConfigurationVO implements InternalIdentity {
         return port;
     }
 
+    public Long getDomainId() {
+        return domainId;
+    }
+
     public void setId(final long id) {
         this.id = id;
     }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java
index 9e27fff..b141f05 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java
@@ -40,29 +40,31 @@ public class LdapContextFactory {
         _ldapConfiguration = ldapConfiguration;
     }
 
-    public LdapContext createBindContext() throws NamingException, IOException {
-        return createBindContext(null);
+    // TODO add optional domain (optional only for backwards compatibility)
+    public LdapContext createBindContext(Long domainId) throws NamingException, IOException {
+        return createBindContext(null, domainId);
     }
 
-    public LdapContext createBindContext(final String providerUrl) throws NamingException, IOException {
-        final String bindPrincipal = _ldapConfiguration.getBindPrincipal();
-        final String bindPassword = _ldapConfiguration.getBindPassword();
-        return createInitialDirContext(bindPrincipal, bindPassword, providerUrl, true);
+    // TODO add optional domain (optional only for backwards compatibility)
+    public LdapContext createBindContext(final String providerUrl, Long domainId) throws NamingException, IOException {
+        final String bindPrincipal = _ldapConfiguration.getBindPrincipal(domainId);
+        final String bindPassword = _ldapConfiguration.getBindPassword(domainId);
+        return createInitialDirContext(bindPrincipal, bindPassword, providerUrl, true, domainId);
     }
 
-    private LdapContext createInitialDirContext(final String principal, final String password, final boolean isSystemContext) throws NamingException, IOException {
-        return createInitialDirContext(principal, password, null, isSystemContext);
+    private LdapContext createInitialDirContext(final String principal, final String password, final boolean isSystemContext, Long domainId) throws NamingException, IOException {
+        return createInitialDirContext(principal, password, null, isSystemContext, domainId);
     }
 
-    private LdapContext createInitialDirContext(final String principal, final String password, final String providerUrl, final boolean isSystemContext)
+    private LdapContext createInitialDirContext(final String principal, final String password, final String providerUrl, final boolean isSystemContext, Long domainId)
         throws NamingException, IOException {
-        Hashtable<String, String> environment = getEnvironment(principal, password, providerUrl, isSystemContext);
+        Hashtable<String, String> environment = getEnvironment(principal, password, providerUrl, isSystemContext, domainId);
         s_logger.debug("initializing ldap with provider url: " + environment.get(Context.PROVIDER_URL));
         return new InitialLdapContext(environment, null);
     }
 
-    public LdapContext createUserContext(final String principal, final String password) throws NamingException, IOException {
-        return createInitialDirContext(principal, password, false);
+    public LdapContext createUserContext(final String principal, final String password, Long domainId) throws NamingException, IOException {
+        return createInitialDirContext(principal, password, false, domainId);
     }
 
     private void enableSSL(final Hashtable<String, String> environment) {
@@ -76,19 +78,19 @@ public class LdapContextFactory {
         }
     }
 
-    private Hashtable<String, String> getEnvironment(final String principal, final String password, final String providerUrl, final boolean isSystemContext) {
+    private Hashtable<String, String> getEnvironment(final String principal, final String password, final String providerUrl, final boolean isSystemContext, Long domainId) {
         final String factory = _ldapConfiguration.getFactory();
-        final String url = providerUrl == null ? _ldapConfiguration.getProviderUrl() : providerUrl;
+        final String url = providerUrl == null ? _ldapConfiguration.getProviderUrl(domainId) : providerUrl;
 
         final Hashtable<String, String> environment = new Hashtable<String, String>();
 
         environment.put(Context.INITIAL_CONTEXT_FACTORY, factory);
         environment.put(Context.PROVIDER_URL, url);
-        environment.put("com.sun.jndi.ldap.read.timeout", _ldapConfiguration.getReadTimeout().toString());
+        environment.put("com.sun.jndi.ldap.read.timeout", _ldapConfiguration.getReadTimeout(domainId).toString());
         environment.put("com.sun.jndi.ldap.connect.pool", "true");
 
         enableSSL(environment);
-        setAuthentication(environment, isSystemContext);
+        setAuthentication(environment, isSystemContext, domainId);
 
         if (principal != null) {
             environment.put(Context.SECURITY_PRINCIPAL, principal);
@@ -101,8 +103,8 @@ public class LdapContextFactory {
         return environment;
     }
 
-    private void setAuthentication(final Hashtable<String, String> environment, final boolean isSystemContext) {
-        final String authentication = _ldapConfiguration.getAuthentication();
+    private void setAuthentication(final Hashtable<String, String> environment, final boolean isSystemContext, final Long domainId) {
+        final String authentication = _ldapConfiguration.getAuthentication(domainId);
 
         if ("none".equals(authentication) && !isSystemContext) {
             environment.put(Context.SECURITY_AUTHENTICATION, "simple");
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java
index 6af2c4e..002242c 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java
@@ -18,36 +18,48 @@ package org.apache.cloudstack.ldap;
 
 import java.util.List;
 
+import org.apache.cloudstack.api.command.LdapAddConfigurationCmd;
+import org.apache.cloudstack.api.command.LdapDeleteConfigurationCmd;
 import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
+import org.apache.cloudstack.api.command.LinkAccountToLdapCmd;
+import org.apache.cloudstack.api.command.LinkDomainToLdapCmd;
 import org.apache.cloudstack.api.response.LdapConfigurationResponse;
 import org.apache.cloudstack.api.response.LdapUserResponse;
 
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.utils.Pair;
 import com.cloud.utils.component.PluggableService;
+import org.apache.cloudstack.api.response.LinkAccountToLdapResponse;
 import org.apache.cloudstack.api.response.LinkDomainToLdapResponse;
 
 public interface LdapManager extends PluggableService {
 
     enum LinkType { GROUP, OU;}
 
-    LdapConfigurationResponse addConfiguration(String hostname, int port) throws InvalidParameterValueException;
+    LdapConfigurationResponse addConfiguration(final LdapAddConfigurationCmd cmd) throws InvalidParameterValueException;
 
-    boolean canAuthenticate(String principal, String password);
+    @Deprecated
+    LdapConfigurationResponse addConfiguration(String hostname, int port, Long domainId) throws InvalidParameterValueException;
+
+    boolean canAuthenticate(String principal, String password, final Long domainId);
 
     LdapConfigurationResponse createLdapConfigurationResponse(LdapConfigurationVO configuration);
 
     LdapUserResponse createLdapUserResponse(LdapUser user);
 
-    LdapConfigurationResponse deleteConfiguration(String hostname) throws InvalidParameterValueException;
+    LdapConfigurationResponse deleteConfiguration(LdapDeleteConfigurationCmd cmd) throws InvalidParameterValueException;
+
+    @Deprecated
+    LdapConfigurationResponse deleteConfiguration(String hostname, int port, Long domainId) throws InvalidParameterValueException;
 
-    LdapUser getUser(final String username) throws NoLdapUserMatchingQueryException;
+    // TODO username is only unique withing domain scope (add domain id to call)
+    LdapUser getUser(final String username, Long domainId) throws NoLdapUserMatchingQueryException;
 
-    LdapUser getUser(String username, String type, String name) throws NoLdapUserMatchingQueryException;
+    LdapUser getUser(String username, String type, String name, Long domainId) throws NoLdapUserMatchingQueryException;
 
-    List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException;
+    List<LdapUser> getUsers(Long domainId) throws NoLdapUserMatchingQueryException;
 
-    List<LdapUser> getUsersInGroup(String groupName) throws NoLdapUserMatchingQueryException;
+    List<LdapUser> getUsersInGroup(String groupName, Long domainId) throws NoLdapUserMatchingQueryException;
 
     boolean isLdapEnabled();
 
@@ -55,7 +67,15 @@ public interface LdapManager extends PluggableService {
 
     List<LdapUser> searchUsers(String query) throws NoLdapUserMatchingQueryException;
 
-    LinkDomainToLdapResponse linkDomainToLdap(Long domainId, String type, String name, short accountType);
+    LinkDomainToLdapResponse linkDomainToLdap(LinkDomainToLdapCmd cmd);
+
+    LdapTrustMapVO getDomainLinkedToLdap(long domainId);
+
+    List<LdapTrustMapVO> getDomainLinkage(long domainId);
+
+    LdapTrustMapVO getAccountLinkedToLdap(long domainId, long accountId);
+
+    LdapTrustMapVO getLinkedLdapGroup(long domainId, String group);
 
-    public LdapTrustMapVO getDomainLinkedToLdap(long domainId);
+    LinkAccountToLdapResponse linkAccountToLdap(LinkAccountToLdapCmd linkAccountToLdapCmd);
 }
\ No newline at end of file
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java
index beb7a61..b82231c 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java
@@ -23,6 +23,7 @@ import java.util.List;
 import javax.inject.Inject;
 import javax.naming.NamingException;
 import javax.naming.ldap.LdapContext;
+import java.util.UUID;
 
 import org.apache.cloudstack.api.LdapValidator;
 import org.apache.cloudstack.api.command.LDAPConfigCmd;
@@ -34,9 +35,11 @@ import org.apache.cloudstack.api.command.LdapImportUsersCmd;
 import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
 import org.apache.cloudstack.api.command.LdapListUsersCmd;
 import org.apache.cloudstack.api.command.LdapUserSearchCmd;
+import org.apache.cloudstack.api.command.LinkAccountToLdapCmd;
 import org.apache.cloudstack.api.command.LinkDomainToLdapCmd;
 import org.apache.cloudstack.api.response.LdapConfigurationResponse;
 import org.apache.cloudstack.api.response.LdapUserResponse;
+import org.apache.cloudstack.api.response.LinkAccountToLdapResponse;
 import org.apache.cloudstack.api.response.LinkDomainToLdapResponse;
 import org.apache.cloudstack.ldap.dao.LdapConfigurationDao;
 import org.apache.cloudstack.ldap.dao.LdapTrustMapDao;
@@ -47,6 +50,9 @@ import org.springframework.stereotype.Component;
 import com.cloud.domain.DomainVO;
 import com.cloud.domain.dao.DomainDao;
 import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.user.Account;
+import com.cloud.user.AccountVO;
+import com.cloud.user.dao.AccountDao;
 import com.cloud.utils.Pair;
 
 @Component
@@ -60,6 +66,9 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
     private DomainDao domainDao;
 
     @Inject
+    private AccountDao accountDao;
+
+    @Inject
     private LdapContextFactory _ldapContextFactory;
 
     @Inject
@@ -85,17 +94,32 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
     }
 
     @Override
-    public LdapConfigurationResponse addConfiguration(final String hostname, final int port) throws InvalidParameterValueException {
-        LdapConfigurationVO configuration = _ldapConfigurationDao.findByHostname(hostname);
+    public LdapConfigurationResponse addConfiguration(final LdapAddConfigurationCmd cmd) throws InvalidParameterValueException {
+        return addConfigurationInternal(cmd.getHostname(),cmd.getPort(),cmd.getDomainId());
+    }
+
+    @Override // TODO make private
+    public LdapConfigurationResponse addConfiguration(final String hostname, int port, final Long domainId) throws InvalidParameterValueException {
+        return addConfigurationInternal(hostname,port,domainId);
+    }
+
+    private LdapConfigurationResponse addConfigurationInternal(final String hostname, int port, final Long domainId) throws InvalidParameterValueException {
+        // TODO evaluate what the right default should be
+        if(port <= 0) {
+            port = 389;
+        }
+
+        // hostname:port is unique for domain binding
+        LdapConfigurationVO configuration = _ldapConfigurationDao.find(hostname, port, domainId);
         if (configuration == null) {
             LdapContext context = null;
             try {
                 final String providerUrl = "ldap://" + hostname + ":" + port;
-                context = _ldapContextFactory.createBindContext(providerUrl);
-                configuration = new LdapConfigurationVO(hostname, port);
+                context = _ldapContextFactory.createBindContext(providerUrl,domainId);
+                configuration = new LdapConfigurationVO(hostname, port, domainId);
                 _ldapConfigurationDao.persist(configuration);
-                s_logger.info("Added new ldap server with hostname: " + hostname);
-                return new LdapConfigurationResponse(hostname, port);
+                s_logger.info("Added new ldap server with url: " + providerUrl + (domainId == null ? "": " for domain " + domainId));
+                return createLdapConfigurationResponse(configuration);
             } catch (NamingException | IOException e) {
                 s_logger.debug("NamingException while doing an LDAP bind", e);
                 throw new InvalidParameterValueException("Unable to bind to the given LDAP server");
@@ -107,10 +131,18 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
         }
     }
 
+    /**
+     * TODO decide if the principal is good enough to get the domain id or we need to add it as parameter
+     * @param principal
+     * @param password
+     * @param domainId
+     * @return
+     */
     @Override
-    public boolean canAuthenticate(final String principal, final String password) {
+    public boolean canAuthenticate(final String principal, final String password, final Long domainId) {
         try {
-            final LdapContext context = _ldapContextFactory.createUserContext(principal, password);
+            // TODO return the right account for this user
+            final LdapContext context = _ldapContextFactory.createUserContext(principal, password,domainId);
             closeContext(context);
             return true;
         } catch (NamingException | IOException e) {
@@ -132,10 +164,11 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
 
     @Override
     public LdapConfigurationResponse createLdapConfigurationResponse(final LdapConfigurationVO configuration) {
-        final LdapConfigurationResponse response = new LdapConfigurationResponse();
-        response.setHostname(configuration.getHostname());
-        response.setPort(configuration.getPort());
-        return response;
+        String domainUuid = null;
+        if(configuration.getDomainId() != null) {
+            domainUuid = domainDao.findById(configuration.getDomainId()).getUuid();
+        }
+        return new LdapConfigurationResponse(configuration.getHostname(), configuration.getPort(), domainUuid);
     }
 
     @Override
@@ -151,14 +184,23 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
     }
 
     @Override
-    public LdapConfigurationResponse deleteConfiguration(final String hostname) throws InvalidParameterValueException {
-        final LdapConfigurationVO configuration = _ldapConfigurationDao.findByHostname(hostname);
+    public LdapConfigurationResponse deleteConfiguration(final LdapDeleteConfigurationCmd cmd) throws InvalidParameterValueException {
+        return deleteConfigurationInternal(cmd.getHostname(), cmd.getPort(), cmd.getDomainId());
+    }
+
+    @Override
+    public LdapConfigurationResponse deleteConfiguration(final String hostname, int port, Long domainId) throws InvalidParameterValueException {
+        return deleteConfigurationInternal(hostname, port, domainId);
+    }
+
+    private LdapConfigurationResponse deleteConfigurationInternal(final String hostname, int port, Long domainId) throws InvalidParameterValueException {
+        final LdapConfigurationVO configuration = _ldapConfigurationDao.find(hostname,port,domainId);
         if (configuration == null) {
             throw new InvalidParameterValueException("Cannot find configuration with hostname " + hostname);
         } else {
             _ldapConfigurationDao.remove(configuration.getId());
-            s_logger.info("Removed ldap server with hostname: " + hostname);
-            return new LdapConfigurationResponse(configuration.getHostname(), configuration.getPort());
+            s_logger.info("Removed ldap server with url: " + hostname + ':' + port + (domainId == null ? "" : " for domain id " + domainId));
+            return createLdapConfigurationResponse(configuration);
         }
     }
 
@@ -175,17 +217,18 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
         cmdList.add(LDAPConfigCmd.class);
         cmdList.add(LDAPRemoveCmd.class);
         cmdList.add(LinkDomainToLdapCmd.class);
+        cmdList.add(LinkAccountToLdapCmd.class);
         return cmdList;
     }
 
     @Override
-    public LdapUser getUser(final String username) throws NoLdapUserMatchingQueryException {
+    public LdapUser getUser(final String username, Long domainId) throws NoLdapUserMatchingQueryException {
         LdapContext context = null;
         try {
-            context = _ldapContextFactory.createBindContext();
+            context = _ldapContextFactory.createBindContext(domainId);
 
             final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
-            return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider()).getUser(escapedUsername, context);
+            return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(null)).getUser(escapedUsername, context, domainId);
 
         } catch (NamingException | IOException e) {
             s_logger.debug("ldap Exception: ",e);
@@ -196,26 +239,26 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
     }
 
     @Override
-    public LdapUser getUser(final String username, final String type, final String name) throws NoLdapUserMatchingQueryException {
+    public LdapUser getUser(final String username, final String type, final String name, Long domainId) throws NoLdapUserMatchingQueryException {
         LdapContext context = null;
         try {
-            context = _ldapContextFactory.createBindContext();
+            context = _ldapContextFactory.createBindContext(domainId);
             final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
-            return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider()).getUser(escapedUsername, type, name, context);
+            return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(null)).getUser(escapedUsername, type, name, context, domainId);
         } catch (NamingException | IOException e) {
             s_logger.debug("ldap Exception: ",e);
-            throw new NoLdapUserMatchingQueryException("No Ldap User found for username: "+username + "name: " + name + "of type: " + type);
+            throw new NoLdapUserMatchingQueryException("No Ldap User found for username: "+username + " in group: " + name + " of type: " + type);
         } finally {
             closeContext(context);
         }
     }
 
     @Override
-    public List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException {
+    public List<LdapUser> getUsers(Long domainId) throws NoLdapUserMatchingQueryException {
         LdapContext context = null;
         try {
-            context = _ldapContextFactory.createBindContext();
-            return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider()).getUsers(context);
+            context = _ldapContextFactory.createBindContext(domainId);
+            return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(domainId)).getUsers(context, domainId);
         } catch (NamingException | IOException e) {
             s_logger.debug("ldap Exception: ",e);
             throw new NoLdapUserMatchingQueryException("*");
@@ -225,11 +268,11 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
     }
 
     @Override
-    public List<LdapUser> getUsersInGroup(String groupName) throws NoLdapUserMatchingQueryException {
+    public List<LdapUser> getUsersInGroup(String groupName, Long domainId) throws NoLdapUserMatchingQueryException {
         LdapContext context = null;
         try {
-            context = _ldapContextFactory.createBindContext();
-            return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider()).getUsersInGroup(groupName, context);
+            context = _ldapContextFactory.createBindContext(domainId);
+            return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(domainId)).getUsersInGroup(groupName, context, domainId);
         } catch (NamingException | IOException e) {
             s_logger.debug("ldap NamingException: ",e);
             throw new NoLdapUserMatchingQueryException("groupName=" + groupName);
@@ -247,7 +290,8 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
     public Pair<List<? extends LdapConfigurationVO>, Integer> listConfigurations(final LdapListConfigurationCmd cmd) {
         final String hostname = cmd.getHostname();
         final int port = cmd.getPort();
-        final Pair<List<LdapConfigurationVO>, Integer> result = _ldapConfigurationDao.searchConfigurations(hostname, port);
+        final Long domainId = cmd.getDomainId();
+        final Pair<List<LdapConfigurationVO>, Integer> result = _ldapConfigurationDao.searchConfigurations(hostname, port, domainId);
         return new Pair<List<? extends LdapConfigurationVO>, Integer>(result.first(), result.second());
     }
 
@@ -255,9 +299,10 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
     public List<LdapUser> searchUsers(final String username) throws NoLdapUserMatchingQueryException {
         LdapContext context = null;
         try {
-            context = _ldapContextFactory.createBindContext();
+            // TODO search users per domain (only?)
+            context = _ldapContextFactory.createBindContext(null);
             final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
-            return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider()).getUsers("*" + escapedUsername + "*", context);
+            return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(null)).getUsers("*" + escapedUsername + "*", context, null);
         } catch (NamingException | IOException e) {
             s_logger.debug("ldap Exception: ",e);
             throw new NoLdapUserMatchingQueryException(username);
@@ -267,14 +312,20 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
     }
 
     @Override
-    public LinkDomainToLdapResponse linkDomainToLdap(Long domainId, String type, String name, short accountType) {
+    public LinkDomainToLdapResponse linkDomainToLdap(LinkDomainToLdapCmd cmd) {
+        Validate.isTrue(_ldapConfiguration.getBaseDn(cmd.getDomainId()) == null, "can not configure an ldap server and an ldap group/ou to a domain");
+        Validate.notEmpty(cmd.getLdapDomain(), "ldapDomain cannot be empty, please supply a GROUP or OU name");
+        return linkDomainToLdap(cmd.getDomainId(),cmd.getType(),cmd.getLdapDomain(),cmd.getAccountType());
+    }
+
+    private LinkDomainToLdapResponse linkDomainToLdap(Long domainId, String type, String name, short accountType) {
         Validate.notNull(type, "type cannot be null. It should either be GROUP or OU");
         Validate.notNull(domainId, "domainId cannot be null.");
         Validate.notEmpty(name, "GROUP or OU name cannot be empty");
         //Account type should be 0 or 2. check the constants in com.cloud.user.Account
         Validate.isTrue(accountType==0 || accountType==2, "accountype should be either 0(normal user) or 2(domain admin)");
         LinkType linkType = LdapManager.LinkType.valueOf(type.toUpperCase());
-        LdapTrustMapVO vo = _ldapTrustMapDao.persist(new LdapTrustMapVO(domainId, linkType, name, accountType));
+        LdapTrustMapVO vo = _ldapTrustMapDao.persist(new LdapTrustMapVO(domainId, linkType, name, accountType, 0));
         DomainVO domain = domainDao.findById(vo.getDomainId());
         String domainUuid = "<unknown>";
         if (domain == null) {
@@ -290,4 +341,46 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
     public LdapTrustMapVO getDomainLinkedToLdap(long domainId){
         return _ldapTrustMapDao.findByDomainId(domainId);
     }
+
+    @Override
+    public List<LdapTrustMapVO> getDomainLinkage(long domainId){
+        return _ldapTrustMapDao.searchByDomainId(domainId);
+    }
+
+    public LdapTrustMapVO getAccountLinkedToLdap(long domainId, long accountId){
+        return _ldapTrustMapDao.findByAccount(domainId, accountId);
+    }
+
+    @Override
+    public LdapTrustMapVO getLinkedLdapGroup(long domainId, String group) {
+        return _ldapTrustMapDao.findGroupInDomain(domainId, group);
+    }
+
+    @Override public LinkAccountToLdapResponse linkAccountToLdap(LinkAccountToLdapCmd cmd) {
+        Validate.notNull(_ldapConfiguration.getBaseDn(cmd.getDomainId()), "can not configure an ldap server and an ldap group/ou to a domain");
+        Validate.notNull(cmd.getDomainId(), "domainId cannot be null.");
+        Validate.notEmpty(cmd.getAccountName(), "accountName cannot be empty.");
+        Validate.notEmpty(cmd.getLdapDomain(), "ldapDomain cannot be empty, please supply a GROUP or OU name");
+        Validate.notNull(cmd.getType(), "type cannot be null. It should either be GROUP or OU");
+        Validate.notEmpty(cmd.getLdapDomain(), "GROUP or OU name cannot be empty");
+
+        LinkType linkType = LdapManager.LinkType.valueOf(cmd.getType().toUpperCase());
+        Account account = accountDao.findActiveAccount(cmd.getAccountName(),cmd.getDomainId());
+        if (account == null) {
+            account = new AccountVO(cmd.getAccountName(), cmd.getDomainId(), null, cmd.getAccountType(), UUID.randomUUID().toString());
+            accountDao.persist((AccountVO)account);
+        }
+        Long accountId = account.getAccountId();
+        LdapTrustMapVO vo = _ldapTrustMapDao.persist(new LdapTrustMapVO(cmd.getDomainId(), linkType, cmd.getLdapDomain(), cmd.getAccountType(), accountId));
+        DomainVO domain = domainDao.findById(vo.getDomainId());
+        String domainUuid = "<unknown>";
+        if (domain == null) {
+            s_logger.error("no domain in database for id " + vo.getDomainId());
+        } else {
+            domainUuid = domain.getUuid();
+        }
+
+        LinkAccountToLdapResponse response = new LinkAccountToLdapResponse(domainUuid, vo.getType().toString(), vo.getName(), vo.getAccountType(), account.getUuid(), cmd.getAccountName());
+        return response;
+    }
 }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapTrustMapVO.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapTrustMapVO.java
index 8b13638..c402747 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapTrustMapVO.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapTrustMapVO.java
@@ -45,6 +45,9 @@ public class LdapTrustMapVO implements InternalIdentity {
     @Column(name = "domain_id")
     private long domainId;
 
+    @Column(name = "account_id")
+    private long accountId;
+
     @Column(name = "account_type")
     private short accountType;
 
@@ -52,11 +55,12 @@ public class LdapTrustMapVO implements InternalIdentity {
     public LdapTrustMapVO() {
     }
 
-    public LdapTrustMapVO(long domainId, LdapManager.LinkType type, String name, short accountType) {
+    public LdapTrustMapVO(long domainId, LdapManager.LinkType type, String name, short accountType, long accountId) {
         this.domainId = domainId;
         this.type = type;
         this.name = name;
         this.accountType = accountType;
+        this.accountId = accountId;
     }
 
     @Override
@@ -80,6 +84,10 @@ public class LdapTrustMapVO implements InternalIdentity {
         return accountType;
     }
 
+    public long getAccountId() {
+        return accountId;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
@@ -94,6 +102,9 @@ public class LdapTrustMapVO implements InternalIdentity {
         if (domainId != that.domainId) {
             return false;
         }
+        if (accountId != that.accountId) {
+            return false;
+        }
         if (accountType != that.accountType) {
             return false;
         }
@@ -109,6 +120,7 @@ public class LdapTrustMapVO implements InternalIdentity {
         int result = type.hashCode();
         result = 31 * result + name.hashCode();
         result = 31 * result + (int) (domainId ^ (domainId >>> 32));
+        result = 31 * result + (int) (accountId ^ (accountId >>> 32));
         result = 31 * result + (int) accountType;
         return result;
     }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUser.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUser.java
index c4c334b..064ee41 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUser.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUser.java
@@ -16,6 +16,9 @@
 // under the License.
 package org.apache.cloudstack.ldap;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class LdapUser implements Comparable<LdapUser> {
     private final String email;
     private final String principal;
@@ -24,8 +27,10 @@ public class LdapUser implements Comparable<LdapUser> {
     private final String username;
     private final String domain;
     private final boolean disabled;
+    private List<String> memberships;
 
-    public LdapUser(final String username, final String email, final String firstname, final String lastname, final String principal, String domain, boolean disabled) {
+    public LdapUser(final String username, final String email, final String firstname, final String lastname, final String principal, String domain, boolean disabled,
+            List<String> memberships) {
         this.username = username;
         this.email = email;
         this.firstname = firstname;
@@ -33,6 +38,7 @@ public class LdapUser implements Comparable<LdapUser> {
         this.principal = principal;
         this.domain = domain;
         this.disabled = disabled;
+        this.memberships = memberships == null ? new ArrayList<>() : memberships;
     }
 
     @Override
@@ -80,6 +86,9 @@ public class LdapUser implements Comparable<LdapUser> {
         return disabled;
     }
 
+    public List<String> getMemberships() {
+        return memberships;
+    }
 
     @Override
     public int hashCode() {
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUserManager.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUserManager.java
index 4e2bcf8..c9fcaa2 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUserManager.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUserManager.java
@@ -30,17 +30,17 @@ public interface LdapUserManager {
         MICROSOFTAD, OPENLDAP;
     }
 
-    public LdapUser getUser(final String username, final LdapContext context) throws NamingException, IOException;
+    public LdapUser getUser(final String username, final LdapContext context, Long domainId) throws NamingException, IOException;
 
-    public LdapUser getUser(final String username, final String type, final String name, final LdapContext context) throws NamingException, IOException;
+    public LdapUser getUser(final String username, final String type, final String name, final LdapContext context, Long domainId) throws NamingException, IOException;
 
-    public List<LdapUser> getUsers(final LdapContext context) throws NamingException, IOException;
+    public List<LdapUser> getUsers(final LdapContext context, Long domainId) throws NamingException, IOException;
 
-    public List<LdapUser> getUsers(final String username, final LdapContext context) throws NamingException, IOException;
+    public List<LdapUser> getUsers(final String username, final LdapContext context, Long domainId) throws NamingException, IOException;
 
-    public List<LdapUser> getUsersInGroup(String groupName, LdapContext context) throws NamingException;
+    public List<LdapUser> getUsersInGroup(String groupName, LdapContext context, Long domainId) throws NamingException;
 
-    public List<LdapUser> searchUsers(final LdapContext context) throws NamingException, IOException;
+    public List<LdapUser> searchUsers(final LdapContext context, Long domainId) throws NamingException, IOException;
 
-    public List<LdapUser> searchUsers(final String username, final LdapContext context) throws NamingException, IOException;
+    public List<LdapUser> searchUsers(final String username, final LdapContext context, Long domainId) throws NamingException, IOException;
 }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUtils.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUtils.java
index d54a699..da0859f 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUtils.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUtils.java
@@ -16,9 +16,12 @@
 // under the License.
 package org.apache.cloudstack.ldap;
 
+import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
 import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
+import java.util.ArrayList;
+import java.util.List;
 
 public final class LdapUtils {
     public static String escapeLDAPSearchFilter(final String filter) {
@@ -56,6 +59,18 @@ public final class LdapUtils {
         return null;
     }
 
+    public static List<String> getAttributeValues(final Attributes attributes, final String attributeName) throws NamingException {
+        ArrayList<String> memberships = new ArrayList<>();
+        final Attribute attribute = attributes.get(attributeName);
+        if (attribute != null) {
+            NamingEnumeration<?> values = attribute.getAll();
+            while(values.hasMore()) {
+                memberships.add(String.valueOf(values.next()));
+            }
+        }
+        return memberships;
+    }
+
     private LdapUtils() {
     }
 }
\ No newline at end of file
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/OpenLdapUserManagerImpl.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/OpenLdapUserManagerImpl.java
index 0c3e0d7..cb3824a 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/OpenLdapUserManagerImpl.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/OpenLdapUserManagerImpl.java
@@ -50,41 +50,46 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
         _ldapConfiguration = ldapConfiguration;
     }
 
-    protected LdapUser createUser(final SearchResult result) throws NamingException {
+    protected LdapUser createUser(final SearchResult result, Long domainId) throws NamingException {
         final Attributes attributes = result.getAttributes();
 
-        final String username = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getUsernameAttribute());
-        final String email = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getEmailAttribute());
-        final String firstname = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getFirstnameAttribute());
-        final String lastname = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getLastnameAttribute());
+        final String username = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getUsernameAttribute(domainId));
+        final String email = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getEmailAttribute(domainId));
+        final String firstname = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getFirstnameAttribute(domainId));
+        final String lastname = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getLastnameAttribute(domainId));
         final String principal = result.getNameInNamespace();
+        final List<String> memberships = LdapUtils.getAttributeValues(attributes, _ldapConfiguration.getUserMemberOfAttribute(domainId));
 
         String domain = principal.replace("cn=" + LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getCommonNameAttribute()) + ",", "");
-        domain = domain.replace("," + _ldapConfiguration.getBaseDn(), "");
+        domain = domain.replace("," + _ldapConfiguration.getBaseDn(domainId), "");
         domain = domain.replace("ou=", "");
 
         boolean disabled = isUserDisabled(result);
 
-        return new LdapUser(username, email, firstname, lastname, principal, domain, disabled);
+        return new LdapUser(username, email, firstname, lastname, principal, domain, disabled, memberships);
     }
 
-    private String generateSearchFilter(final String username) {
+    private String generateSearchFilter(final String username, Long domainId) {
         final StringBuilder userObjectFilter = new StringBuilder();
         userObjectFilter.append("(objectClass=");
-        userObjectFilter.append(_ldapConfiguration.getUserObject());
+        userObjectFilter.append(_ldapConfiguration.getUserObject(domainId));
         userObjectFilter.append(")");
 
         final StringBuilder usernameFilter = new StringBuilder();
         usernameFilter.append("(");
-        usernameFilter.append(_ldapConfiguration.getUsernameAttribute());
+        usernameFilter.append(_ldapConfiguration.getUsernameAttribute(domainId));
         usernameFilter.append("=");
         usernameFilter.append((username == null ? "*" : username));
         usernameFilter.append(")");
 
         final StringBuilder memberOfFilter = new StringBuilder();
-        if (_ldapConfiguration.getSearchGroupPrinciple() != null) {
-            memberOfFilter.append("(memberof=");
-            memberOfFilter.append(_ldapConfiguration.getSearchGroupPrinciple());
+        if (_ldapConfiguration.getSearchGroupPrinciple(domainId) != null) {
+            if(s_logger.isDebugEnabled()) {
+                s_logger.debug("adding search filter for '" + _ldapConfiguration.getSearchGroupPrinciple(domainId) +
+                "', using " + _ldapConfiguration.getUserMemberOfAttribute(domainId));
+            }
+            memberOfFilter.append("(" + _ldapConfiguration.getUserMemberOfAttribute(domainId) + "=");
+            memberOfFilter.append(_ldapConfiguration.getSearchGroupPrinciple(domainId));
             memberOfFilter.append(")");
         }
 
@@ -98,10 +103,10 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
         return result.toString();
     }
 
-    private String generateGroupSearchFilter(final String groupName) {
+    private String generateGroupSearchFilter(final String groupName, Long domainId) {
         final StringBuilder groupObjectFilter = new StringBuilder();
         groupObjectFilter.append("(objectClass=");
-        groupObjectFilter.append(_ldapConfiguration.getGroupObject());
+        groupObjectFilter.append(_ldapConfiguration.getGroupObject(domainId));
         groupObjectFilter.append(")");
 
         final StringBuilder groupNameFilter = new StringBuilder();
@@ -121,8 +126,8 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
     }
 
     @Override
-    public LdapUser getUser(final String username, final LdapContext context) throws NamingException, IOException {
-        List<LdapUser> result = searchUsers(username, context);
+    public LdapUser getUser(final String username, final LdapContext context, Long domainId) throws NamingException, IOException {
+        List<LdapUser> result = searchUsers(username, context, domainId);
         if (result!= null && result.size() == 1) {
             return result.get(0);
         } else {
@@ -131,29 +136,29 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
     }
 
     @Override
-    public LdapUser getUser(final String username, final String type, final String name, final LdapContext context) throws NamingException, IOException {
+    public LdapUser getUser(final String username, final String type, final String name, final LdapContext context, Long domainId) throws NamingException, IOException {
         String basedn;
         if("OU".equals(type)) {
             basedn = name;
         } else {
-            basedn = _ldapConfiguration.getBaseDn();
+            basedn = _ldapConfiguration.getBaseDn(domainId);
         }
 
         final StringBuilder userObjectFilter = new StringBuilder();
         userObjectFilter.append("(objectClass=");
-        userObjectFilter.append(_ldapConfiguration.getUserObject());
+        userObjectFilter.append(_ldapConfiguration.getUserObject(domainId));
         userObjectFilter.append(")");
 
         final StringBuilder usernameFilter = new StringBuilder();
         usernameFilter.append("(");
-        usernameFilter.append(_ldapConfiguration.getUsernameAttribute());
+        usernameFilter.append(_ldapConfiguration.getUsernameAttribute(domainId));
         usernameFilter.append("=");
         usernameFilter.append((username == null ? "*" : username));
         usernameFilter.append(")");
 
         final StringBuilder memberOfFilter = new StringBuilder();
         if ("GROUP".equals(type)) {
-            memberOfFilter.append("(").append(getMemberOfAttribute()).append("=");
+            memberOfFilter.append("(").append(getMemberOfAttribute(domainId)).append("=");
             memberOfFilter.append(name);
             memberOfFilter.append(")");
         }
@@ -165,21 +170,21 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
         searchQuery.append(memberOfFilter);
         searchQuery.append(")");
 
-        return searchUser(basedn, searchQuery.toString(), context);
+        return searchUser(basedn, searchQuery.toString(), context, domainId);
     }
 
-    protected String getMemberOfAttribute() {
-        return "memberof";
+    protected String getMemberOfAttribute(final Long domainId) {
+        return _ldapConfiguration.getUserMemberOfAttribute(domainId);
     }
 
     @Override
-    public List<LdapUser> getUsers(final LdapContext context) throws NamingException, IOException {
-        return getUsers(null, context);
+    public List<LdapUser> getUsers(final LdapContext context, Long domainId) throws NamingException, IOException {
+        return getUsers(null, context, domainId);
     }
 
     @Override
-    public List<LdapUser> getUsers(final String username, final LdapContext context) throws NamingException, IOException {
-        List<LdapUser> users = searchUsers(username, context);
+    public List<LdapUser> getUsers(final String username, final LdapContext context, Long domainId) throws NamingException, IOException {
+        List<LdapUser> users = searchUsers(username, context, domainId);
 
         if (CollectionUtils.isNotEmpty(users)) {
             Collections.sort(users);
@@ -188,13 +193,13 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
     }
 
     @Override
-    public List<LdapUser> getUsersInGroup(String groupName, LdapContext context) throws NamingException {
-        String attributeName = _ldapConfiguration.getGroupUniqueMemeberAttribute();
+    public List<LdapUser> getUsersInGroup(String groupName, LdapContext context, Long domainId) throws NamingException {
+        String attributeName = _ldapConfiguration.getGroupUniqueMemberAttribute(domainId);
         final SearchControls controls = new SearchControls();
         controls.setSearchScope(_ldapConfiguration.getScope());
         controls.setReturningAttributes(new String[] {attributeName});
 
-        NamingEnumeration<SearchResult> result = context.search(_ldapConfiguration.getBaseDn(), generateGroupSearchFilter(groupName), controls);
+        NamingEnumeration<SearchResult> result = context.search(_ldapConfiguration.getBaseDn(domainId), generateGroupSearchFilter(groupName, domainId), controls);
 
         final List<LdapUser> users = new ArrayList<LdapUser>();
         //Expecting only one result which has all the users
@@ -205,7 +210,7 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
             while (values.hasMoreElements()) {
                 String userdn = String.valueOf(values.nextElement());
                 try{
-                    users.add(getUserForDn(userdn, context));
+                    users.add(getUserForDn(userdn, context, domainId));
                 } catch (NamingException e){
                     s_logger.info("Userdn: " + userdn + " Not Found:: Exception message: " + e.getMessage());
                 }
@@ -217,39 +222,42 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
         return users;
     }
 
-    private LdapUser getUserForDn(String userdn, LdapContext context) throws NamingException {
+    private LdapUser getUserForDn(String userdn, LdapContext context, Long domainId) throws NamingException {
         final SearchControls controls = new SearchControls();
         controls.setSearchScope(_ldapConfiguration.getScope());
-        controls.setReturningAttributes(_ldapConfiguration.getReturnAttributes());
+        controls.setReturningAttributes(_ldapConfiguration.getReturnAttributes(domainId));
 
-        NamingEnumeration<SearchResult> result = context.search(userdn, "(objectClass=" + _ldapConfiguration.getUserObject() + ")", controls);
+        NamingEnumeration<SearchResult> result = context.search(userdn, "(objectClass=" + _ldapConfiguration.getUserObject(domainId) + ")", controls);
         if (result.hasMoreElements()) {
-            return createUser(result.nextElement());
+            return createUser(result.nextElement(), domainId);
         } else {
             throw new NamingException("No user found for dn " + userdn);
         }
     }
 
     @Override
-    public List<LdapUser> searchUsers(final LdapContext context) throws NamingException, IOException {
-        return searchUsers(null, context);
+    public List<LdapUser> searchUsers(final LdapContext context, Long domainId) throws NamingException, IOException {
+        return searchUsers(null, context, domainId);
     }
 
     protected boolean isUserDisabled(SearchResult result) throws NamingException {
         return false;
     }
 
-    public LdapUser searchUser(final String basedn, final String searchString, final LdapContext context) throws NamingException, IOException {
+    public LdapUser searchUser(final String basedn, final String searchString, final LdapContext context, Long domainId) throws NamingException, IOException {
         final SearchControls searchControls = new SearchControls();
 
         searchControls.setSearchScope(_ldapConfiguration.getScope());
-        searchControls.setReturningAttributes(_ldapConfiguration.getReturnAttributes());
+        searchControls.setReturningAttributes(_ldapConfiguration.getReturnAttributes(domainId));
 
         NamingEnumeration<SearchResult> results = context.search(basedn, searchString, searchControls);
+        if(s_logger.isDebugEnabled()) {
+            s_logger.debug("searching user(s) with filter: \"" + searchString + "\"");
+        }
         final List<LdapUser> users = new ArrayList<LdapUser>();
         while (results.hasMoreElements()) {
             final SearchResult result = results.nextElement();
-                users.add(createUser(result));
+                users.add(createUser(result, domainId));
         }
 
         if (users.size() == 1) {
@@ -260,28 +268,28 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
     }
 
     @Override
-    public List<LdapUser> searchUsers(final String username, final LdapContext context) throws NamingException, IOException {
+    public List<LdapUser> searchUsers(final String username, final LdapContext context, Long domainId) throws NamingException, IOException {
 
         final SearchControls searchControls = new SearchControls();
 
         searchControls.setSearchScope(_ldapConfiguration.getScope());
-        searchControls.setReturningAttributes(_ldapConfiguration.getReturnAttributes());
+        searchControls.setReturningAttributes(_ldapConfiguration.getReturnAttributes(domainId));
 
-        String basedn = _ldapConfiguration.getBaseDn();
+        String basedn = _ldapConfiguration.getBaseDn(domainId);
         if (StringUtils.isBlank(basedn)) {
             throw new IllegalArgumentException("ldap basedn is not configured");
         }
         byte[] cookie = null;
-        int pageSize = _ldapConfiguration.getLdapPageSize();
+        int pageSize = _ldapConfiguration.getLdapPageSize(domainId);
         context.setRequestControls(new Control[]{new PagedResultsControl(pageSize, Control.NONCRITICAL)});
         final List<LdapUser> users = new ArrayList<LdapUser>();
         NamingEnumeration<SearchResult> results;
         do {
-            results = context.search(basedn, generateSearchFilter(username), searchControls);
+            results = context.search(basedn, generateSearchFilter(username, domainId), searchControls);
             while (results.hasMoreElements()) {
                 final SearchResult result = results.nextElement();
                 if (!isUserDisabled(result)) {
-                    users.add(createUser(result));
+                    users.add(createUser(result, domainId));
                 }
             }
             Control[] contextControls = context.getResponseControls();
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java
index a2d5e65..e99c78b 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java
@@ -23,8 +23,19 @@ import org.apache.cloudstack.ldap.LdapConfigurationVO;
 import com.cloud.utils.Pair;
 import com.cloud.utils.db.GenericDao;
 
+/**
+ * TODO the domain value null now searches for that specifically and there is no way to search for all domains
+ */
 public interface LdapConfigurationDao extends GenericDao<LdapConfigurationVO, Long> {
+    /**
+     * @deprecated there might well be more then one ldap implementation on a host and or a double binding of several domains
+     * @param hostname
+     * @return
+     */
+    @Deprecated
     LdapConfigurationVO findByHostname(String hostname);
 
-    Pair<List<LdapConfigurationVO>, Integer> searchConfigurations(String hostname, int port);
+    LdapConfigurationVO find(String hostname, int port, Long domainId);
+
+    Pair<List<LdapConfigurationVO>, Integer> searchConfigurations(String hostname, int port, Long domainId);
 }
\ No newline at end of file
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDaoImpl.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDaoImpl.java
index 8125f8c..fa4c0af 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDaoImpl.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDaoImpl.java
@@ -32,7 +32,8 @@ import com.cloud.utils.db.SearchCriteria.Op;
 @Component
 public class LdapConfigurationDaoImpl extends GenericDaoBase<LdapConfigurationVO, Long> implements LdapConfigurationDao {
     private final SearchBuilder<LdapConfigurationVO> hostnameSearch;
-    private final SearchBuilder<LdapConfigurationVO> listAllConfigurationsSearch;
+    private final SearchBuilder<LdapConfigurationVO> listGlobalConfigurationsSearch;
+    private final SearchBuilder<LdapConfigurationVO> listDomainConfigurationsSearch;
 
     public LdapConfigurationDaoImpl() {
         super();
@@ -40,10 +41,16 @@ public class LdapConfigurationDaoImpl extends GenericDaoBase<LdapConfigurationVO
         hostnameSearch.and("hostname", hostnameSearch.entity().getHostname(), SearchCriteria.Op.EQ);
         hostnameSearch.done();
 
-        listAllConfigurationsSearch = createSearchBuilder();
-        listAllConfigurationsSearch.and("hostname", listAllConfigurationsSearch.entity().getHostname(), Op.EQ);
-        listAllConfigurationsSearch.and("port", listAllConfigurationsSearch.entity().getPort(), Op.EQ);
-        listAllConfigurationsSearch.done();
+        listGlobalConfigurationsSearch = createSearchBuilder();
+        listGlobalConfigurationsSearch.and("hostname", listGlobalConfigurationsSearch.entity().getHostname(), Op.EQ);
+        listGlobalConfigurationsSearch.and("port", listGlobalConfigurationsSearch.entity().getPort(), Op.EQ);
+        listGlobalConfigurationsSearch.and("domain_id", listGlobalConfigurationsSearch.entity().getDomainId(),SearchCriteria.Op.NULL);
+        listGlobalConfigurationsSearch.done();
+        listDomainConfigurationsSearch = createSearchBuilder();
+        listDomainConfigurationsSearch.and("hostname", listDomainConfigurationsSearch.entity().getHostname(), Op.EQ);
+        listDomainConfigurationsSearch.and("port", listDomainConfigurationsSearch.entity().getPort(), Op.EQ);
+        listDomainConfigurationsSearch.and("domain_id", listDomainConfigurationsSearch.entity().getDomainId(), Op.EQ);
+        listDomainConfigurationsSearch.done();
     }
 
     @Override
@@ -54,11 +61,31 @@ public class LdapConfigurationDaoImpl extends GenericDaoBase<LdapConfigurationVO
     }
 
     @Override
-    public Pair<List<LdapConfigurationVO>, Integer> searchConfigurations(final String hostname, final int port) {
-        final SearchCriteria<LdapConfigurationVO> sc = listAllConfigurationsSearch.create();
+    public LdapConfigurationVO find(String hostname, int port, Long domainId) {
+        SearchCriteria<LdapConfigurationVO> sc = getSearchCriteria(hostname, port, domainId);
+        return findOneBy(sc);
+    }
+
+    @Override
+    public Pair<List<LdapConfigurationVO>, Integer> searchConfigurations(final String hostname, final int port, final Long domainId) {
+        SearchCriteria<LdapConfigurationVO> sc = getSearchCriteria(hostname, port, domainId);
+        return searchAndCount(sc, null);
+    }
+
+    private SearchCriteria<LdapConfigurationVO> getSearchCriteria(String hostname, int port, Long domainId) {
+        SearchCriteria<LdapConfigurationVO> sc;
+        if (domainId == null) {
+            sc = listDomainConfigurationsSearch.create();
+        } else {
+            sc = listDomainConfigurationsSearch.create();
+            sc.setParameters("domain_id", domainId);
+        }
         if (hostname != null) {
             sc.setParameters("hostname", hostname);
         }
-        return searchAndCount(sc, null);
+        if (port > 0) {
+            sc.setParameters("port", port);
+        }
+        return sc;
     }
 }
\ No newline at end of file
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapTrustMapDao.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapTrustMapDao.java
index 7ef3799..c3d2f8a 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapTrustMapDao.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapTrustMapDao.java
@@ -22,6 +22,11 @@ import org.apache.cloudstack.ldap.LdapTrustMapVO;
 
 import com.cloud.utils.db.GenericDao;
 
+import java.util.List;
+
 public interface LdapTrustMapDao extends GenericDao<LdapTrustMapVO, Long> {
     LdapTrustMapVO findByDomainId(long domainId);
+    LdapTrustMapVO findByAccount(long domainId, Long accountId);
+    LdapTrustMapVO findGroupInDomain(long domainId, String group);
+    List<LdapTrustMapVO> searchByDomainId(long domainId);
 }
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapTrustMapDaoImpl.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapTrustMapDaoImpl.java
index 5783098..0ecd341 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapTrustMapDaoImpl.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapTrustMapDaoImpl.java
@@ -26,21 +26,55 @@ import org.springframework.stereotype.Component;
 
 import com.cloud.utils.db.GenericDaoBase;
 
+import java.util.List;
+
 @Component
 public class LdapTrustMapDaoImpl extends GenericDaoBase<LdapTrustMapVO, Long> implements LdapTrustMapDao  {
     private final SearchBuilder<LdapTrustMapVO> domainIdSearch;
+    private final SearchBuilder<LdapTrustMapVO> groupSearch;
 
     public LdapTrustMapDaoImpl() {
         super();
         domainIdSearch = createSearchBuilder();
         domainIdSearch.and("domainId", domainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
+        domainIdSearch.and("account_id", domainIdSearch.entity().getAccountId(),SearchCriteria.Op.EQ);
         domainIdSearch.done();
+        groupSearch = createSearchBuilder();
+        groupSearch.and("domainId", groupSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
+        groupSearch.and("name", groupSearch.entity().getName(),SearchCriteria.Op.EQ);
+        groupSearch.done();
     }
 
     @Override
     public LdapTrustMapVO findByDomainId(long domainId) {
         final SearchCriteria<LdapTrustMapVO> sc = domainIdSearch.create();
         sc.setParameters("domainId", domainId);
+        sc.setParameters("account_id", 0);
+        return findOneBy(sc);
+    }
+
+    @Override
+    public LdapTrustMapVO findByAccount(long domainId, Long accountId) {
+        final SearchCriteria<LdapTrustMapVO> sc = domainIdSearch.create();
+        sc.setParameters("domainId", domainId);
+        sc.setParameters("account_id", accountId);
         return findOneBy(sc);
     }
+
+    @Override
+    public LdapTrustMapVO findGroupInDomain(long domainId, String group){
+        final SearchCriteria<LdapTrustMapVO> sc = groupSearch.create();
+        sc.setParameters("domainId", domainId);
+        sc.setParameters("name", group);
+        return findOneBy(sc);
+
+    }
+
+    @Override
+    public List<LdapTrustMapVO> searchByDomainId(long domainId) {
+        final SearchCriteria<LdapTrustMapVO> sc = domainIdSearch.create();
+        sc.setParameters("domainId", domainId);
+        return search(sc,null);
+    }
+
 }
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/ADLdapUserManagerImplSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/ADLdapUserManagerImplSpec.groovy
index 93b1b17..4b631b4 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/ADLdapUserManagerImplSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/ADLdapUserManagerImplSpec.groovy
@@ -69,13 +69,13 @@ class ADLdapUserManagerImplSpec extends spock.lang.Specification {
 
     def "test getUsersInGroup null group"() {
         ldapConfiguration.getScope() >> SearchControls.SUBTREE_SCOPE
-        ldapConfiguration.getReturnAttributes() >> ["username", "firstname", "lastname", "email"]
-        ldapConfiguration.getBaseDn() >>> [null, null, "DC=cloud,DC=citrix,DC=com"]
+        ldapConfiguration.getReturnAttributes(null) >> ["username", "firstname", "lastname", "email"]
+        ldapConfiguration.getBaseDn(null) >>> [null, null, "DC=cloud,DC=citrix,DC=com"]
 
         LdapContext context = Mock(LdapContext);
 
         when:
-            def result = adLdapUserManager.getUsersInGroup(group, context)
+            def result = adLdapUserManager.getUsersInGroup(group, context,null)
         then:
             thrown(IllegalArgumentException)
         where:
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAuthenticatorSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAuthenticatorSpec.groovy
index ca19e8c..1ff5fce 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAuthenticatorSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAuthenticatorSpec.groovy
@@ -49,8 +49,8 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
         def ldapUser = Mock(LdapUser)
         ldapUser.isDisabled() >> false
         ldapManager.isLdapEnabled() >> true
-        ldapManager.getUser("rmurphy") >> ldapUser
-        ldapManager.canAuthenticate(_, _) >> false
+        ldapManager.getUser("rmurphy", null) >> ldapUser
+        ldapManager.canAuthenticate(_, _, _) >> false
 
         UserAccountDao userAccountDao = Mock(UserAccountDao)
         userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
@@ -84,8 +84,8 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
         def ldapUser = Mock(LdapUser)
         ldapUser.isDisabled() >> false
         ldapManager.isLdapEnabled() >> true
-        ldapManager.canAuthenticate(_, _) >> true
-        ldapManager.getUser("rmurphy") >> ldapUser
+        ldapManager.canAuthenticate(_, _, _) >> true
+        ldapManager.getUser("rmurphy", null) >> ldapUser
 
         UserAccountDao userAccountDao = Mock(UserAccountDao)
         userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
@@ -144,7 +144,7 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
         userAccountDao.getUserAccount(username, domainId) >> userAccount
         userAccount.getId() >> 1
         ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)2)
-        ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", true)
+        ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", true, null)
         //user should be disabled in cloudstack
         accountManager.disableUser(1) >> userAccount
 
@@ -173,8 +173,8 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
         ldapManager.isLdapEnabled() >> true
         userAccountDao.getUserAccount(username, domainId) >> null
         ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)0)
-        ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false)
-        ldapManager.canAuthenticate(_,_) >> true
+        ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false, null)
+        ldapManager.canAuthenticate(_, _, _) >> true
         //user should be created in cloudstack
         accountManager.createUserAccount(username, "", "firstname", "lastname", "email", null, username, (short) 2, domainId, username, null, _, _, User.Source.LDAP) >> Mock(UserAccount)
 
@@ -206,8 +206,8 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
         userAccount.getId() >> 1
         userAccount.getState() >> Account.State.disabled.toString()
         ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)2)
-        ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false)
-        ldapManager.canAuthenticate(_,_) >> true
+        ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false, null)
+        ldapManager.canAuthenticate(_, _, _) >> true
         //user should be enabled in cloudstack if disabled
         accountManager.enableUser(1) >> userAccount
 
@@ -237,8 +237,8 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
         UserAccount userAccount = Mock(UserAccount)
         userAccountDao.getUserAccount(username, domainId) >> userAccount
         ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)2)
-        ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false)
-        ldapManager.canAuthenticate(_,_) >> false
+        ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false, null)
+        ldapManager.canAuthenticate(_, _, _) >> false
 
         when:
         Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate(username, "password", domainId, null)
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationDaoImplSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationDaoImplSpec.groovy
index 1448909..e94b0d4 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationDaoImplSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationDaoImplSpec.groovy
@@ -22,8 +22,8 @@ class LdapConfigurationDaoImplSpec extends spock.lang.Specification {
     def "Test setting up of a LdapConfigurationDao"() {
 		given: "We have an LdapConfigurationDao implementation"
         def ldapConfigurationDaoImpl = new LdapConfigurationDaoImpl();
-		expect: "that hostnameSearch and listAllConfigurationsSearch is configured"
+		expect: "that hostnameSearch and listDomainConfigurationsSearch is configured"
         ldapConfigurationDaoImpl.hostnameSearch != null;
-        ldapConfigurationDaoImpl.listAllConfigurationsSearch != null
+        ldapConfigurationDaoImpl.listDomainConfigurationsSearch != null
     }
 }
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationSpec.groovy
index 6f967cc..ec84d38 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationSpec.groovy
@@ -19,55 +19,26 @@ package groovy.org.apache.cloudstack.ldap
 import org.apache.cloudstack.framework.config.ConfigKey
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import com.cloud.utils.Pair
-import org.apache.cloudstack.api.ServerApiException
 import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl
 import org.apache.cloudstack.framework.config.impl.ConfigurationVO
 import org.apache.cloudstack.ldap.LdapConfiguration
 import org.apache.cloudstack.ldap.LdapConfigurationVO
-import org.apache.cloudstack.ldap.LdapManager
 import org.apache.cloudstack.ldap.LdapUserManager
 import org.apache.cloudstack.ldap.dao.LdapConfigurationDao
-import org.apache.cxf.common.util.StringUtils
 
 import javax.naming.directory.SearchControls
 
 class LdapConfigurationSpec extends spock.lang.Specification {
     def "Test that getAuthentication returns none"() {
         given: "We have a ConfigDao, LdapManager and LdapConfiguration"
-        def configDao = Mock(ConfigurationDao)
         def ldapConfigurationDao = Mock(LdapConfigurationDao)
-        def ldapConfiguration = new LdapConfiguration(configDao, ldapConfigurationDao)
+        def ldapConfiguration = new LdapConfiguration(ldapConfigurationDao)
         when: "Get authentication is called"
         String authentication = ldapConfiguration.getAuthentication()
         then: "none should be returned"
         authentication == "none"
     }
 
-    def "Test that getAuthentication returns simple"() {
-        given: "We have a configDao, LdapManager and LdapConfiguration with bind principle and password set"
-        def configDao = Mock(ConfigurationDao)
-        def ldapConfigurationDao = Mock(LdapConfigurationDao)
-        def ldapConfiguration = new LdapConfiguration(configDao, ldapConfigurationDao)
-        configDao.getValue("ldap.bind.password") >> "password"
-        configDao.getValue("ldap.bind.principal") >> "cn=rmurphy,dc=cloudstack,dc=org"
-        when: "Get authentication is called"
-        String authentication = ldapConfiguration.getAuthentication()
-        then: "authentication should be set to simple"
-        authentication == "simple"
-    }
-
-    def "Test that getBaseDn returns dc=cloudstack,dc=org"() {
-        given: "We have a ConfigDao, LdapManager and ldapConfiguration with a baseDn value set."
-        def configDao = Mock(ConfigurationDao)
-        configDao.getValue("ldap.basedn") >> "dc=cloudstack,dc=org"
-        def ldapConfigurationDao = Mock(LdapConfigurationDao)
-        def ldapConfiguration = new LdapConfiguration(configDao, ldapConfigurationDao)
-        when: "Get basedn is called"
-        String baseDn = ldapConfiguration.getBaseDn();
-        then: "The set baseDn should be returned"
-        baseDn == "dc=cloudstack,dc=org"
-    }
-
     def "Test that getEmailAttribute returns mail"() {
         given: "Given that we have a ConfigDao, LdapManager and LdapConfiguration"
         def configDao = Mock(ConfigurationDao)
@@ -178,87 +149,12 @@ class LdapConfigurationSpec extends spock.lang.Specification {
         LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapConfigurationDao)
 
         when: "A request is made to get the providerUrl"
-        String providerUrl = ldapConfiguration.getProviderUrl()
+        String providerUrl = ldapConfiguration.getProviderUrl(_)
 
         then: "The providerUrl should be given."
         providerUrl == "ldap://localhost:389"
     }
 
-    def "Test that get search group principle returns successfully"() {
-        given: "We have a ConfigDao with a value for ldap.search.group.principle and an LdapConfiguration"
-        def configDao = Mock(ConfigurationDao)
-        configDao.getValue("ldap.search.group.principle") >> "cn=cloudstack,cn=users,dc=cloudstack,dc=org"
-        def ldapConfigurationDao = Mock(LdapConfigurationDao)
-        LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapConfigurationDao)
-
-        when: "A request is made to get the search group principle"
-        String result = ldapConfiguration.getSearchGroupPrinciple();
-
-        then: "The result holds the same value configDao did"
-        result == "cn=cloudstack,cn=users,dc=cloudstack,dc=org"
-    }
-
-    def "Test that getTrustStorePassword resopnds"() {
-        given: "We have a ConfigDao with a value for truststore password"
-        def configDao = Mock(ConfigurationDao)
-        configDao.getValue("ldap.truststore.password") >> "password"
-        def ldapConfigurationDao = Mock(LdapConfigurationDao)
-        LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapConfigurationDao)
-
-        when: "A request is made to get the truststore password"
-        String result = ldapConfiguration.getTrustStorePassword()
-
-        then: "The result is password"
-        result == "password";
-    }
-
-    def "Test that getSSLStatus can be true"() {
-        given: "We have a ConfigDao with values for truststore and truststore password set"
-        def configDao = Mock(ConfigurationDao)
-        configDao.getValue("ldap.truststore") >> "/tmp/ldap.ts"
-        configDao.getValue("ldap.truststore.password") >> "password"
-        def ldapConfigurationDao = Mock(LdapConfigurationDao)
-        LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapConfigurationDao)
-
-        when: "A request is made to get the status of SSL"
-        boolean result = ldapConfiguration.getSSLStatus();
-
-        then: "The response should be true"
-        result == true
-    }
-
-    def "Test getgroupobject"() {
-        given: "We have configdao for ldap group object"
-        def configDao = Mock(ConfigurationDao)
-        configDao.getValue("ldap.group.object") >> groupObject
-
-        def ldapConfigurationDao = Mock(LdapConfigurationDao)
-        LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapConfigurationDao)
-        def expectedResult = groupObject == null ? "groupOfUniqueNames" : groupObject
-
-        def result = ldapConfiguration.getGroupObject()
-        expect:
-        result == expectedResult
-        where:
-        groupObject << [null, "", "groupOfUniqueNames"]
-    }
-
-    def "Test getGroupUniqueMemeberAttribute"() {
-        given: "We have configdao for ldap group object"
-        def configDao = Mock(ConfigurationDao)
-        configDao.getValue("ldap.group.user.uniquemember") >> groupObject
-
-        def ldapConfigurationDao = Mock(LdapConfigurationDao)
-        LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapConfigurationDao)
-        def expectedResult = groupObject == null ? "uniquemember" : groupObject
-
-        def result = ldapConfiguration.getGroupUniqueMemeberAttribute()
-        expect:
-        result == expectedResult
-        where:
-        groupObject << [null, "", "uniquemember"]
-    }
-
     def "Test getReadTimeout"() {
         given: "We have configdao for ldap group object"
         def configDao = Mock(ConfigurationDao)
@@ -275,7 +171,7 @@ class LdapConfigurationSpec extends spock.lang.Specification {
 
         def expected = timeout == null ? 1000 : timeout.toLong() //1000 is the default value
 
-        def result = ldapConfiguration.getReadTimeout()
+        def result = ldapConfiguration.getReadTimeout(null)
         expect:
         result == expected
         where:
@@ -298,7 +194,7 @@ class LdapConfigurationSpec extends spock.lang.Specification {
 
         def expected = provider.equalsIgnoreCase("microsoftad") ? LdapUserManager.Provider.MICROSOFTAD : LdapUserManager.Provider.OPENLDAP //"openldap" is the default value
 
-        def result = ldapConfiguration.getLdapProvider()
+        def result = ldapConfiguration.getLdapProvider(null)
         expect:
         println "asserting for provider configuration: " + provider
         result == expected
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy
index 1540883..eead0bc 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy
@@ -22,7 +22,6 @@ import spock.lang.Shared
 
 import javax.naming.NamingException
 import javax.naming.directory.SearchControls
-import javax.naming.ldap.LdapContext
 
 class LdapContextFactorySpec extends spock.lang.Specification {
     @Shared
@@ -41,7 +40,7 @@ class LdapContextFactorySpec extends spock.lang.Specification {
         ldapConfiguration = Mock(LdapConfiguration)
 
         ldapConfiguration.getFactory() >> "com.sun.jndi.ldap.LdapCtxFactory"
-        ldapConfiguration.getProviderUrl() >> "ldap://localhost:389"
+        ldapConfiguration.getProviderUrl(_) >> "ldap://localhost:389"
         ldapConfiguration.getAuthentication() >> "none"
         ldapConfiguration.getScope() >> SearchControls.SUBTREE_SCOPE
         ldapConfiguration.getReturnAttributes() >> ["uid", "mail", "cn"]
@@ -49,11 +48,11 @@ class LdapContextFactorySpec extends spock.lang.Specification {
         ldapConfiguration.getEmailAttribute() >> "mail"
         ldapConfiguration.getFirstnameAttribute() >> "givenname"
         ldapConfiguration.getLastnameAttribute() >> "sn"
-        ldapConfiguration.getBaseDn() >> "dc=cloudstack,dc=org"
+        ldapConfiguration.getBaseDn(_) >> "dc=cloudstack,dc=org"
 		ldapConfiguration.getSSLStatus() >> true
 		ldapConfiguration.getTrustStore() >> "/tmp/ldap.ts"
 		ldapConfiguration.getTrustStorePassword() >> "password"
-        ldapConfiguration.getReadTimeout() >> 1000
+        ldapConfiguration.getReadTimeout(_) >> 1000
         ldapConfiguration.getLdapPageSize() >> 1
 
         username = "rmurphy"
@@ -87,7 +86,7 @@ class LdapContextFactorySpec extends spock.lang.Specification {
         def result = ldapContextFactory.getEnvironment(null, null, null, true)
 
 		then: "The resulting values should be set"
-        result['java.naming.provider.url'] == ldapConfiguration.getProviderUrl()
+        result['java.naming.provider.url'] == ldapConfiguration.getProviderUrl(null)
         result['java.naming.factory.initial'] == ldapConfiguration.getFactory()
         result['java.naming.security.principal'] == null
         result['java.naming.security.authentication'] == ldapConfiguration.getAuthentication()
@@ -102,7 +101,7 @@ class LdapContextFactorySpec extends spock.lang.Specification {
 		def result = ldapContextFactory.getEnvironment(principal, password, null, false)
 
 		then: "The resulting values should be set"
-		result['java.naming.provider.url'] == ldapConfiguration.getProviderUrl()
+		result['java.naming.provider.url'] == ldapConfiguration.getProviderUrl(null)
 		result['java.naming.factory.initial'] == ldapConfiguration.getFactory()
 		result['java.naming.security.principal'] == principal
 		result['java.naming.security.authentication'] == "simple"
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapCreateAccountCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapCreateAccountCmdSpec.groovy
index a0b20bb..db4fa23 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapCreateAccountCmdSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapCreateAccountCmdSpec.groovy
@@ -16,54 +16,13 @@
 // under the License.
 package groovy.org.apache.cloudstack.ldap
 
-import com.cloud.exception.InvalidParameterValueException
-import org.apache.cloudstack.api.ServerApiException
-import org.apache.cloudstack.api.command.LdapAddConfigurationCmd
-import org.apache.cloudstack.api.response.LdapConfigurationResponse
-
 import org.apache.cloudstack.ldap.LdapUser;
 import org.apache.cloudstack.ldap.LdapManager;
 
-import org.apache.cloudstack.api.command.LdapCreateAccountCmd;
-import org.apache.cloudstack.context.CallContext;
-
-import com.cloud.user.AccountService;
-import com.cloud.user.UserAccount;
-import com.cloud.user.UserAccountVO
-import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
-
-import javax.naming.NamingException
+import org.apache.cloudstack.api.command.LdapCreateAccountCmd
+import com.cloud.user.AccountService
 
 class LdapCreateAccountCmdSpec extends spock.lang.Specification {
-
-    def "Test failure to retrive LDAP user"() {
-        given: "We have an LdapManager, AccountService and LdapCreateAccountCmd and LDAP user that doesn't exist"
-        LdapManager ldapManager = Mock(LdapManager)
-        ldapManager.getUser(_) >> { throw new NoLdapUserMatchingQueryException() }
-        AccountService accountService = Mock(AccountService)
-        def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService])
-        ldapCreateAccountCmd.getCurrentContext() >> Mock(CallContext)
-        CallContext context = ldapCreateAccountCmd.getCurrentContext()
-        when: "An an account is created"
-        ldapCreateAccountCmd.execute()
-        then: "It fails and an exception is thrown"
-        thrown ServerApiException
-    }
-
-    def "Test failed creation due to a null response from cloudstack account creater"() {
-        given: "We have an LdapManager, AccountService and LdapCreateAccountCmd"
-        LdapManager ldapManager = Mock(LdapManager)
-        ldapManager.getUser(_) >> new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false)
-        AccountService accountService = Mock(AccountService)
-        def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService])
-        ldapCreateAccountCmd.getCurrentContext() >> Mock(CallContext)
-        ldapCreateAccountCmd.createCloudstackUserAccount(_, _, _) >> null
-        when: "Cloudstack fail to create the user"
-        ldapCreateAccountCmd.execute()
-        then: "An exception is thrown"
-        thrown ServerApiException
-    }
-
     def "Test command name"() {
         given: "We have an LdapManager, AccountService and LdapCreateAccountCmd"
         LdapManager ldapManager = Mock(LdapManager)
@@ -105,7 +64,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
         AccountService accountService = Mock(AccountService)
         def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService);
         when: "a user with an username, email, firstname and lastname is validated"
-        def result = ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", "lastname", "principal", "domain", false))
+        def result = ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", "lastname", "principal", "domain", false, null))
         then: "the result is true"
         result == true
     }
@@ -116,7 +75,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
         AccountService accountService = Mock(AccountService)
         def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
         when: "A user with no email address attempts to validate"
-        ldapCreateAccountCmd.validateUser(new LdapUser("username", null, "firstname", "lastname", "principal", "domain", false))
+        ldapCreateAccountCmd.validateUser(new LdapUser("username", null, "firstname", "lastname", "principal", "domain", false, null))
         then: "An exception is thrown"
         thrown Exception
     }
@@ -138,7 +97,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
         AccountService accountService = Mock(AccountService)
         def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
         when: "A user with no lastname attempts to validate"
-        ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", null, "principal", "domain", false))
+        ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", null, "principal", "domain", false, null))
         then: "An exception is thown"
         thrown Exception
     }
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapDeleteConfigurationCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapDeleteConfigurationCmdSpec.groovy
index 31d56ef..caa5247 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapDeleteConfigurationCmdSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapDeleteConfigurationCmdSpec.groovy
@@ -27,7 +27,7 @@ class LdapDeleteConfigurationCmdSpec extends spock.lang.Specification {
     def "Test failed response from execute"() {
 		given: "We have an LdapManager and LdapDeleteConfigurationCmd"
 		def ldapManager = Mock(LdapManager)
-        ldapManager.deleteConfiguration(_) >> { throw new InvalidParameterValueException() }
+        ldapManager.deleteConfiguration(_, 0, null) >> { throw new InvalidParameterValueException() }
         def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
 		when:"LdapDeleteConfigurationCmd is executed and no configuration exists"
         ldapDeleteConfigurationCmd.execute()
@@ -48,7 +48,7 @@ class LdapDeleteConfigurationCmdSpec extends spock.lang.Specification {
     def "Test successful response from execute"() {
 		given: "We have an LdapManager and LdapDeleteConfigurationCmd"
 		def ldapManager = Mock(LdapManager)
-		ldapManager.deleteConfiguration(_) >> new LdapConfigurationResponse("localhost")
+		ldapManager.deleteConfiguration(_, 0, null) >> new LdapConfigurationResponse("localhost")
 		def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
 		when: "LdapDeleteConfigurationCmd is executed"
 		ldapDeleteConfigurationCmd.execute()
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy
index 434151a..68b9108 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy
@@ -24,10 +24,8 @@ import com.cloud.user.DomainService
 import com.cloud.user.User
 import com.cloud.user.UserAccountVO
 import com.cloud.user.UserVO
-import org.apache.cloudstack.api.command.LdapCreateAccountCmd
 import org.apache.cloudstack.api.command.LdapImportUsersCmd
 import org.apache.cloudstack.api.response.LdapUserResponse
-import org.apache.cloudstack.context.CallContext
 import org.apache.cloudstack.ldap.LdapManager
 import org.apache.cloudstack.ldap.LdapUser
 
@@ -53,9 +51,9 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         def accountService = Mock(AccountService)
 
         List<LdapUser> users = new ArrayList()
-        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        ldapManager.getUsers() >> users
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        ldapManager.getUsers(null) >> users
         LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
         LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
         ldapManager.createLdapUserResponse(_) >>> [response1, response2]
@@ -81,9 +79,9 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         def accountService = Mock(AccountService)
 
         List<LdapUser> users = new ArrayList()
-        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        ldapManager.getUsersInGroup("TestGroup") >> users
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        ldapManager.getUsersInGroup("TestGroup", null) >> users
         LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
         LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
         ldapManager.createLdapUserResponse(_) >>> [response1, response2]
@@ -110,9 +108,9 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         def accountService = Mock(AccountService)
 
         List<LdapUser> users = new ArrayList()
-        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        ldapManager.getUsersInGroup("TestGroup") >> users
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        ldapManager.getUsersInGroup("TestGroup", null) >> users
         LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
         LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
         ldapManager.createLdapUserResponse(_) >>> [response1, response2]
@@ -139,9 +137,9 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         def accountService = Mock(AccountService)
 
         List<LdapUser> users = new ArrayList()
-        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        ldapManager.getUsers() >> users
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        ldapManager.getUsers(null) >> users
         LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
         LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
         ldapManager.createLdapUserResponse(_) >>> [response1, response2]
@@ -169,8 +167,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         ldapImportUsersCmd.domainId = varDomainId
         ldapImportUsersCmd.groupName = varGroupName
 
-        def ldapUser1 = new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false)
-        def ldapUser2 = new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false);
+        def ldapUser1 = new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null)
+        def ldapUser2 = new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null);
 
         Domain domain = new DomainVO(expectedDomainName, 1L, 1L, expectedDomainName, UUID.randomUUID().toString());
         if (varDomainId != null) {
@@ -204,8 +202,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
         def ldapManager = Mock(LdapManager)
         List<LdapUser> users = new ArrayList()
-        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        ldapManager.getUsers() >> users
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        ldapManager.getUsers(null) >> users
         LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
         ldapManager.createLdapUserResponse(_) >>> response1
 
@@ -234,8 +232,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
         def ldapManager = Mock(LdapManager)
         List<LdapUser> users = new ArrayList()
-        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        ldapManager.getUsers() >> users
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        ldapManager.getUsers(null) >> users
         LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
         ldapManager.createLdapUserResponse(_) >>> response1
 
@@ -263,8 +261,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
         def ldapManager = Mock(LdapManager)
         List<LdapUser> users = new ArrayList()
-        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
-        ldapManager.getUsers() >> users
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
+        ldapManager.getUsers(null) >> users
         LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
         ldapManager.createLdapUserResponse(_) >>> response1
 
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListUsersCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListUsersCmdSpec.groovy
index 5247a1e..d6410d9 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListUsersCmdSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListUsersCmdSpec.groovy
@@ -40,7 +40,7 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
     def "Test successful empty response from execute"() {
 		given: "We have a LdapManager with no users, QueryService and a LdapListUsersCmd"
 	def ldapManager = Mock(LdapManager)
-	ldapManager.getUsers() >> {throw new NoLdapUserMatchingQueryException()}
+	ldapManager.getUsers(null) >> {throw new NoLdapUserMatchingQueryException()}
 		def queryService = Mock(QueryService)
 	def ldapListUsersCmd = new LdapListUsersCmd(ldapManager, queryService)
 		when: "LdapListUsersCmd is executed"
@@ -53,8 +53,8 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
 		given: "We have an LdapManager, one user, QueryService and a LdapListUsersCmd"
 		def ldapManager = Mock(LdapManager)
 		List<LdapUser> users = new ArrayList()
-		users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false))
-		ldapManager.getUsers() >> users
+		users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false, null))
+		ldapManager.getUsers(null) >> users
 		LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
 		ldapManager.createLdapUserResponse(_) >> response
 		def queryService = Mock(QueryService)
@@ -92,7 +92,7 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
 
 		queryService.searchForUsers(_) >> queryServiceResponse
 
-		def ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false)
+		def ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false, null)
 		def ldapListUsersCmd = new LdapListUsersCmd(ldapManager,queryService)
 
 		when: "isACloudstackUser is executed"
@@ -109,7 +109,7 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
 
 		queryService.searchForUsers(_) >> new ListResponse<UserResponse>()
 
-		def ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false)
+		def ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false, null)
 		def ldapListUsersCmd = new LdapListUsersCmd(ldapManager,queryService)
 
 		when: "isACloudstackUser is executed"
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapManagerImplSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapManagerImplSpec.groovy
index c9af002..238b279 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapManagerImplSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapManagerImplSpec.groovy
@@ -52,7 +52,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         ldapContextFactory.createBindContext() >> { throw new NoLdapUserMatchingQueryException() }
         def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
         when: "We search for a user but there is a bind issue"
-        ldapManager.getUser("rmurphy")
+        ldapManager.getUser("rmurphy", null)
         then: "an exception is thrown"
         thrown NoLdapUserMatchingQueryException
     }
@@ -68,7 +68,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         ldapContextFactory.createBindContext() >> { throw new NamingException() }
         def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
         when: "We search for a group of users but there is a bind issue"
-        ldapManager.getUsers()
+        ldapManager.getUsers(null)
         then: "An exception is thrown"
         thrown NoLdapUserMatchingQueryException
     }
@@ -116,7 +116,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
         when: "A ldap user response is generated"
         def result = ldapManager.createLdapUserResponse(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org",
-                "engineering", false))
+                "engineering", false, null))
         then: "The result of the response should match the given ldap user"
         result.username == "rmurphy"
         result.email == "rmurphy@test.com"
@@ -136,11 +136,11 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         ldapUserManagerFactory.getInstance(_) >> ldapUserManager
         ldapContextFactory.createBindContext() >> null
         List<LdapUser> users = new ArrayList<>();
-        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false))
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false, null))
         ldapUserManager.getUsers(_) >> users;
         def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
         when: "We search for a group of users"
-        def result = ldapManager.getUsers()
+        def result = ldapManager.getUsers(null)
         then: "A list greater than 0 is returned"
         result.size() > 0;
     }
@@ -154,10 +154,10 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         def ldapConfiguration = Mock(LdapConfiguration)
         ldapUserManagerFactory.getInstance(_) >> ldapUserManager
         ldapContextFactory.createBindContext() >> null
-        ldapUserManager.getUser(_, _) >> new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false)
+        ldapUserManager.getUser(_, _, _) >> new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false, null)
         def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
         when: "We search for a user"
-        def result = ldapManager.getUser("rmurphy")
+        def result = ldapManager.getUser("rmurphy", null)
         then: "The user is returned"
         result.username == "rmurphy"
         result.email == "rmurphy@test.com"
@@ -192,9 +192,9 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         ldapUserManagerFactory.getInstance(_) >> ldapUserManager
         def ldapConfiguration = Mock(LdapConfiguration)
         def ldapManager = Spy(LdapManagerImpl, constructorArgs: [ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration])
-        ldapManager.getUser(_) >> { new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null) }
+        ldapManager.getUser(_, null) >> { new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null) }
         when: "The user attempts to authenticate with a bad password"
-        def result = ldapManager.canAuthenticate("rmurphy", "password")
+        def result = ldapManager.canAuthenticate("rmurphy", "password", null)
         then: "The authentication fails"
         result == false
     }
@@ -210,7 +210,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         ldapConfigurationDao.findByHostname(_) >> null
         def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
         when: "A ldap configuration that doesn't exist is deleted"
-        ldapManager.deleteConfiguration("localhost")
+        ldapManager.deleteConfiguration("localhost", 0, null)
         then: "A exception is thrown"
         thrown InvalidParameterValueException
     }
@@ -242,9 +242,9 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         def ldapConfiguration = Mock(LdapConfiguration)
         ldapUserManagerFactory.getInstance(_) >> ldapUserManager
         def ldapManager = Spy(LdapManagerImpl, constructorArgs: [ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration])
-        ldapManager.getUser(_) >> { new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null) }
+        ldapManager.getUser(_, null) >> { new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null) }
         when: "A user authenticates"
-        def result = ldapManager.canAuthenticate("rmurphy", "password")
+        def result = ldapManager.canAuthenticate("rmurphy", "password", null)
         then: "The result is true"
         result == true
     }
@@ -265,7 +265,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         ldapConfigurationDao.remove(_) >> null
         def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
         when: "A ldap configuration is deleted"
-        def result = ldapManager.deleteConfiguration("localhost")
+        def result = ldapManager.deleteConfiguration("localhost", 0, null)
         then: "The deleted configuration is returned"
         result.hostname == "localhost"
         result.port == 389
@@ -282,7 +282,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         ldapContextFactory.createBindContext() >> null;
 
         List<LdapUser> users = new ArrayList<LdapUser>();
-        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null))
         ldapUserManager.getUsers(_, _) >> users;
 
         def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
@@ -424,11 +424,11 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         ldapUserManagerFactory.getInstance(_) >> ldapUserManager
         ldapContextFactory.createBindContext() >> null
         List<LdapUser> users = new ArrayList<>();
-        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", "engineering", false))
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", "engineering", false, null))
         ldapUserManager.getUsersInGroup("engineering", _) >> users;
         def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
         when: "We search for a group of users"
-        def result = ldapManager.getUsersInGroup("engineering")
+        def result = ldapManager.getUsersInGroup("engineering", null)
         then: "A list greater of size one is returned"
         result.size() == 1;
     }
@@ -524,7 +524,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         def type = "GROUP"
         def name = "CN=test,DC=citrix,DC=com"
 
-        ldapUserManager.getUser(username, type, name, _) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", true)
+        ldapUserManager.getUser(username, type, name, _) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", true, null)
 
         when:
             LdapUser user = ldapManager.getUser(username, type, name)
@@ -574,7 +574,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         def type = "GROUP"
         def name = "CN=test,DC=citrix,DC=com"
 
-        ldapUserManager.getUser(username, type, name, _) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false)
+        ldapUserManager.getUser(username, type, name, _) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false, null)
 
         when:
         LdapUser user = ldapManager.getUser(username, type, name)
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapSearchUserCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapSearchUserCmdSpec.groovy
index 5551087..8936024 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapSearchUserCmdSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapSearchUserCmdSpec.groovy
@@ -48,7 +48,7 @@ class LdapSearchUserCmdSpec extends spock.lang.Specification {
 	given: "We have an Ldap manager and ldap user search cmd"
         def ldapManager = Mock(LdapManager)
 		List<LdapUser> users = new ArrayList()
-		users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false))
+		users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false, null))
 		ldapManager.searchUsers(_) >> users
 		LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
 		ldapManager.createLdapUserResponse(_) >> response
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserSpec.groovy
index 8ddfc9a..36b37ca 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserSpec.groovy
@@ -22,7 +22,7 @@ class LdapUserSpec extends spock.lang.Specification {
 
     def "Testing LdapUsers hashCode generation"() {
 		given:
-		def userA = new LdapUser(usernameA, "", "", "", "", "", false)
+		def userA = new LdapUser(usernameA, "", "", "", "", "", false, null)
 		expect:
 		userA.hashCode() == usernameA.hashCode()
 		where:
@@ -31,8 +31,8 @@ class LdapUserSpec extends spock.lang.Specification {
 
     def "Testing that LdapUser successfully gives the correct result for a compare to"() {
 		given: "You have created two LDAP user objects"
-		def userA = new LdapUser(usernameA, "", "", "", "", "", false)
-		def userB = new LdapUser(usernameB, "", "", "", "", "", false)
+		def userA = new LdapUser(usernameA, "", "", "", "", "", false, null)
+		def userB = new LdapUser(usernameB, "", "", "", "", "", false, null)
 		expect: "That when compared the result is less than or equal to 0"
 		userA.compareTo(userB) <= 0
 		where: "The following values are used"
@@ -43,8 +43,8 @@ class LdapUserSpec extends spock.lang.Specification {
 
     def "Testing that LdapUsers equality"() {
 		given:
-		def userA = new LdapUser(usernameA, "", "", "", "", "", false)
-		def userB = new LdapUser(usernameB, "", "", "", "", "", false)
+		def userA = new LdapUser(usernameA, "", "", "", "", "", false, null)
+		def userB = new LdapUser(usernameB, "", "", "", "", "", false, null)
 		expect:
 		userA.equals(userA) == true
 		userA.equals(new Object()) == false
@@ -56,7 +56,7 @@ class LdapUserSpec extends spock.lang.Specification {
 
     def "Testing that the username is correctly set with the ldap object"() {
         given: "You have created a LDAP user object with a username"
-	def user = new LdapUser(username, "", "", "", "", "", false)
+	def user = new LdapUser(username, "", "", "", "", "", false, null)
         expect: "The username is equal to the given data source"
         user.getUsername() == username
         where: "The username is set to "
@@ -65,7 +65,7 @@ class LdapUserSpec extends spock.lang.Specification {
 
     def "Testing the email is correctly set with the ldap object"() {
         given: "You have created a LDAP user object with a email"
-	def user = new LdapUser("", email, "", "", "", "", false)
+	def user = new LdapUser("", email, "", "", "", "", false, null)
         expect: "The email is equal to the given data source"
         user.getEmail() == email
         where: "The email is set to "
@@ -74,7 +74,7 @@ class LdapUserSpec extends spock.lang.Specification {
 
     def "Testing the firstname is correctly set with the ldap object"() {
         given: "You have created a LDAP user object with a firstname"
-	def user = new LdapUser("", "", firstname, "", "", "", false)
+	def user = new LdapUser("", "", firstname, "", "", "", false, null)
         expect: "The firstname is equal to the given data source"
         user.getFirstname() == firstname
         where: "The firstname is set to "
@@ -83,7 +83,7 @@ class LdapUserSpec extends spock.lang.Specification {
 
     def "Testing the lastname is correctly set with the ldap object"() {
         given: "You have created a LDAP user object with a lastname"
-	def user = new LdapUser("", "", "", lastname, "", "", false)
+	def user = new LdapUser("", "", "", lastname, "", "", false, null)
         expect: "The lastname is equal to the given data source"
         user.getLastname() == lastname
         where: "The lastname is set to "
@@ -92,7 +92,7 @@ class LdapUserSpec extends spock.lang.Specification {
 
     def "Testing the principal is correctly set with the ldap object"() {
         given: "You have created a LDAP user object with a principal"
-	def user = new LdapUser("", "", "", "", principal, "", false)
+	def user = new LdapUser("", "", "", "", principal, "", false, null)
         expect: "The principal is equal to the given data source"
         user.getPrincipal() == principal
 	where: "The principal is set to "
@@ -101,7 +101,7 @@ class LdapUserSpec extends spock.lang.Specification {
 
     def "Testing the domain is correctly set with the ldap object"() {
 	given: "You have created a LDAP user object with a principal"
-	def user = new LdapUser("", "", "", "", "", domain, false)
+	def user = new LdapUser("", "", "", "", "", domain, false, null)
 	expect: "The principal is equal to the given data source"
 	user.getDomain() == domain
 	where: "The username is set to "
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LinkDomainToLdapCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LinkDomainToLdapCmdSpec.groovy
index bad41e8..46b00a9 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LinkDomainToLdapCmdSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LinkDomainToLdapCmdSpec.groovy
@@ -79,7 +79,7 @@ class LinkDomainToLdapCmdSpec extends Specification {
 
         LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(domainId, type, name, (short)accountType)
         _ldapManager.linkDomainToLdap(_,_,_,_) >> response
-        _ldapManager.getUser(username, type, name) >> new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", name, "ccp", true)
+        _ldapManager.getUser(username, type, name) >> new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", name, "ccp", true, null)
 
         linkDomainToLdapCmd.admin = username
         linkDomainToLdapCmd.type = type
@@ -107,7 +107,7 @@ class LinkDomainToLdapCmdSpec extends Specification {
 
         LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(domainId.toString(), type, name, (short)accountType)
         _ldapManager.linkDomainToLdap(_,_,_,_) >> response
-        _ldapManager.getUser(username, type, name) >> new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", name, "ccp", false)
+        _ldapManager.getUser(username, type, name) >> new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", name, "ccp", false, null)
 
         _accountService.getActiveAccountByName(username, domainId) >> Mock(Account)
 
@@ -204,7 +204,7 @@ class LinkDomainToLdapCmdSpec extends Specification {
 
         LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(domainId.toString(), type, name, (short)accountType)
         _ldapManager.linkDomainToLdap(_,_,_,_) >> response
-        _ldapManager.getUser(username, type, name) >> new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", name, "ccp", false)
+        _ldapManager.getUser(username, type, name) >> new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", name, "ccp", false, null)
 
         _accountService.getActiveAccountByName(username, domainId) >> null
         UserAccount userAccount = Mock(UserAccount)
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/OpenLdapUserManagerSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/OpenLdapUserManagerSpec.groovy
index cb08c8f..40daa41 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/OpenLdapUserManagerSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/OpenLdapUserManagerSpec.groovy
@@ -17,14 +17,12 @@
 package groovy.org.apache.cloudstack.ldap
 
 import org.apache.cloudstack.ldap.LdapConfiguration
-import org.apache.cloudstack.ldap.LdapUserManager
 import org.apache.cloudstack.ldap.OpenLdapUserManagerImpl
 import spock.lang.Shared
 
 import javax.naming.NamingException
 import javax.naming.directory.Attribute
 import javax.naming.directory.Attributes
-import javax.naming.directory.InitialDirContext
 import javax.naming.directory.SearchControls
 import javax.naming.directory.SearchResult
 import javax.naming.ldap.InitialLdapContext
@@ -167,12 +165,12 @@ class OpenLdapUserManagerSpec extends spock.lang.Specification {
         ldapConfiguration.getEmailAttribute() >> "mail"
         ldapConfiguration.getFirstnameAttribute() >> "givenname"
         ldapConfiguration.getLastnameAttribute() >> "sn"
-        ldapConfiguration.getBaseDn() >> "dc=cloudstack,dc=org"
+        ldapConfiguration.getBaseDn(_) >> "dc=cloudstack,dc=org"
         ldapConfiguration.getCommonNameAttribute() >> "cn"
         ldapConfiguration.getGroupObject() >> "groupOfUniqueNames"
-        ldapConfiguration.getGroupUniqueMemeberAttribute() >> "uniquemember"
+        ldapConfiguration.getGroupUniqueMemberAttribute(_) >> "uniquemember"
         ldapConfiguration.getLdapPageSize() >> 1
-        ldapConfiguration.getReadTimeout() >> 1000
+        ldapConfiguration.getReadTimeout(_) >> 1000
 
         username = "rmurphy"
         email = "rmurphy@test.com"
@@ -186,7 +184,7 @@ class OpenLdapUserManagerSpec extends spock.lang.Specification {
         def attributes = createUserAttributes(username, email, firstname, lastname)
         def search = createSearchResult(attributes)
         def userManager = new OpenLdapUserManagerImpl(ldapConfiguration)
-        def result = userManager.createUser(search)
+        def result = userManager.createUser(search,)
 
         expect: "The crated user the data supplied from LDAP"
 
@@ -290,7 +288,7 @@ class OpenLdapUserManagerSpec extends spock.lang.Specification {
         def ldapUserManager = new OpenLdapUserManagerImpl(ldapConfiguration)
 
         when: "A request for users is made"
-        def result = ldapUserManager.getUsersInGroup("engineering", createGroupSearchContextOneUser())
+        def result = ldapUserManager.getUsersInGroup("engineering", createGroupSearchContextOneUser(),)
         then: "one user is returned"
         result.size() == 1
     }
@@ -300,7 +298,7 @@ class OpenLdapUserManagerSpec extends spock.lang.Specification {
         def ldapUserManager = new OpenLdapUserManagerImpl(ldapConfiguration)
 
         when: "A request for users is made"
-        def result = ldapUserManager.getUsersInGroup("engineering", createGroupSearchContextNoUser())
+        def result = ldapUserManager.getUsersInGroup("engineering", createGroupSearchContextNoUser(),)
         then: "no user is returned"
         result.size() == 0
     }
diff --git a/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LdapConfigurationChanger.java b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LdapConfigurationChanger.java
new file mode 100644
index 0000000..61aa959
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LdapConfigurationChanger.java
@@ -0,0 +1,56 @@
+// 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.
+package org.apache.cloudstack.api.command;
+
+import java.lang.reflect.Field;
+
+interface LdapConfigurationChanger {
+    /**
+     * sets a possibly not accessible field of the target object.
+     * @param target the object to set a hidden fields value in.
+     * @param name the name of the field to set.
+     * @param o intended value for the field "name"
+     * @throws IllegalAccessException
+     * @throws NoSuchFieldException
+     */
+    default void setHiddenField(Object target, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException {
+        Class<?> klas = target.getClass();
+        Field f = getFirstFoundField(name, klas);
+        f.setAccessible(true);
+        f.set(target, o);
+    }
+
+    /**
+     * the first field found by this name in the class "klas" or any of it's superclasses except for {@code Object}. Implementers of this interface can decide to also return any field in implemented interfaces or in {@code Object}.
+     *
+     * @param name of the field to find
+     * @param klas class to gat a field by name "name" from
+     * @return a {@code Field} by the name "name"
+     * @throws NoSuchFieldException
+     */
+    default Field getFirstFoundField(String name, Class<?> klas) throws NoSuchFieldException {
+        try {
+            return klas.getDeclaredField(name);
+        } catch (NoSuchFieldException e) {
+            Class<?> parent = klas.getSuperclass();
+            if(parent.equals(Object.class)) {
+                throw e;
+            }
+            return getFirstFoundField(name, parent);
+        }
+    }
+}
\ No newline at end of file
diff --git a/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LdapCreateAccountCmdTest.java b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LdapCreateAccountCmdTest.java
new file mode 100644
index 0000000..a4eccbf
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LdapCreateAccountCmdTest.java
@@ -0,0 +1,72 @@
+// 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.
+package org.apache.cloudstack.api.command;
+
+import com.cloud.user.Account;
+import com.cloud.user.AccountService;
+import org.apache.cloudstack.acl.RoleService;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.ldap.LdapManager;
+import org.apache.cloudstack.ldap.LdapUser;
+import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.isNull;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class LdapCreateAccountCmdTest implements LdapConfigurationChanger {
+    @Mock
+    LdapManager ldapManager;
+    @Mock
+    AccountService accountService;
+    @Mock
+    RoleService roleService;
+
+    LdapCreateAccountCmd ldapCreateAccountCmd;
+
+    @Before
+    public void setUp() throws NoSuchFieldException, IllegalAccessException {
+        ldapCreateAccountCmd = spy(new LdapCreateAccountCmd(ldapManager, accountService));
+        ldapCreateAccountCmd.roleService = roleService;
+        setHiddenField(ldapCreateAccountCmd,"accountType", Account.ACCOUNT_TYPE_DOMAIN_ADMIN);
+    }
+
+    @Test(expected = ServerApiException.class)
+    public void failureToRetrieveLdapUser() throws Exception {
+        // We have an LdapManager, AccountService and LdapCreateAccountCmd and LDAP user that doesn't exist
+        when(ldapManager.getUser(anyString(), isNull(Long.class))).thenThrow(NoLdapUserMatchingQueryException.class);
+        ldapCreateAccountCmd.execute();
+        fail("An exception should have been thrown: " + ServerApiException.class);
+    }
+
+    @Test(expected = ServerApiException.class)
+    public void failedCreationDueToANullResponseFromCloudstackAccountCreater() throws Exception {
+        // We have an LdapManager, AccountService and LdapCreateAccountCmd
+        LdapUser mrMurphy = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null);
+        when(ldapManager.getUser(anyString(), isNull(Long.class))).thenReturn(mrMurphy);
+        ldapCreateAccountCmd.execute();
+        fail("An exception should have been thrown: " + ServerApiException.class);
+    }
+}
\ No newline at end of file
diff --git a/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LdapImportUsersCmdTest.java b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LdapImportUsersCmdTest.java
new file mode 100644
index 0000000..8db2673
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LdapImportUsersCmdTest.java
@@ -0,0 +1,85 @@
+// 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.
+package org.apache.cloudstack.api.command;
+
+import com.cloud.domain.Domain;
+import com.cloud.domain.DomainVO;
+import com.cloud.user.Account;
+import com.cloud.user.AccountService;
+import com.cloud.user.DomainService;
+import org.apache.cloudstack.acl.RoleService;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.apache.cloudstack.api.response.LdapUserResponse;
+import org.apache.cloudstack.ldap.LdapManager;
+import org.apache.cloudstack.ldap.LdapUser;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class LdapImportUsersCmdTest implements LdapConfigurationChanger {
+    @Mock
+    LdapManager ldapManager;
+    @Mock
+    AccountService accountService;
+    @Mock
+    DomainService domainService;
+    @Mock
+    RoleService roleService;
+
+    LdapImportUsersCmd ldapImportUsersCmd;
+
+    @Before
+    public void setUp() throws NoSuchFieldException, IllegalAccessException {
+        ldapImportUsersCmd = spy(new LdapImportUsersCmd(ldapManager, domainService, accountService));
+        ldapImportUsersCmd.roleService = roleService;
+        setHiddenField(ldapImportUsersCmd, "accountType", Account.ACCOUNT_TYPE_DOMAIN_ADMIN);
+    }
+
+    @Test
+    public void successfulResponseFromExecute() throws Exception {
+        List<LdapUser> users = new ArrayList();
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null));
+        users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false, null));
+        when(ldapManager.getUsers(null)).thenReturn(users);
+        LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering");
+        LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering");
+        when(ldapManager.createLdapUserResponse(any(LdapUser.class))).thenReturn(response1).thenReturn(response2);
+
+
+        Domain domain = new DomainVO("engineering", 1L, 1L, "engineering", UUID.randomUUID().toString());
+        when(domainService.getDomainByName("engineering", 1L)).thenReturn(null, domain);
+        when(domainService.createDomain(eq("engineering"), eq(1L), eq("engineering"), anyString())).thenReturn(domain);
+
+        ldapImportUsersCmd.execute();
+        ListResponse<LdapUserResponse> resp = (ListResponse<LdapUserResponse>)ldapImportUsersCmd.getResponseObject();
+        assertEquals(" when LdapListUsersCmd is executed, a list of size 2 should be returned", 2, resp.getResponses().size());
+    }
+}
\ No newline at end of file
diff --git a/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LinkAccountToLdapCmdTest.java b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LinkAccountToLdapCmdTest.java
new file mode 100644
index 0000000..35aed6a
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LinkAccountToLdapCmdTest.java
@@ -0,0 +1,97 @@
+// 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.
+
+package org.apache.cloudstack.api.command;
+
+import com.cloud.user.Account;
+import com.cloud.user.AccountService;
+import com.cloud.user.User;
+import com.cloud.user.UserAccountVO;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.response.LinkAccountToLdapResponse;
+import org.apache.cloudstack.ldap.LdapManager;
+import org.apache.cloudstack.ldap.LdapUser;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class LinkAccountToLdapCmdTest implements LdapConfigurationChanger {
+
+    @Mock
+    LdapManager ldapManager;
+    @Mock
+    AccountService accountService;
+
+    LinkAccountToLdapCmd linkAccountToLdapCmd;
+
+    @Before
+    public void setUp() throws NoSuchFieldException, IllegalAccessException {
+        linkAccountToLdapCmd = new LinkAccountToLdapCmd();
+        setHiddenField(linkAccountToLdapCmd, "_ldapManager", ldapManager);
+        setHiddenField(linkAccountToLdapCmd, "_accountService", accountService);
+    }
+
+    @Test
+    public void execute() throws Exception {
+        //      test with valid params and with admin who doesnt exist in cloudstack
+        long domainId = 1;
+        String type = "GROUP";
+        String ldapDomain = "CN=test,DC=ccp,DC=Citrix,DC=com";
+        short accountType = Account.ACCOUNT_TYPE_DOMAIN_ADMIN;
+        String username = "admin";
+        long accountId = 24;
+        String accountName = "test";
+
+        setHiddenField(linkAccountToLdapCmd, "ldapDomain", ldapDomain);
+        setHiddenField(linkAccountToLdapCmd, "admin", username);
+        setHiddenField(linkAccountToLdapCmd, "type", type);
+        setHiddenField(linkAccountToLdapCmd, "domainId", domainId);
+        setHiddenField(linkAccountToLdapCmd, "accountType", accountType);
+        setHiddenField(linkAccountToLdapCmd, "accountName", accountName);
+
+
+        LinkAccountToLdapResponse response = new LinkAccountToLdapResponse(String.valueOf(domainId), type, ldapDomain, (short)accountType, username, accountName);
+        when(ldapManager.linkAccountToLdap(linkAccountToLdapCmd)).thenReturn(response);
+        when(ldapManager.getUser(username, type, ldapDomain, 1L))
+                .thenReturn(new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", ldapDomain, "ccp", false, null));
+
+        when(accountService.getActiveAccountByName(username, domainId)).thenReturn(null);
+        UserAccountVO userAccount =  new UserAccountVO();
+        userAccount.setAccountId(24);
+        when(accountService.createUserAccount(eq(username), eq(""), eq("Admin"), eq("Admin"), eq("admin@ccp.citrix.com"), isNull(String.class),
+                eq(username), eq(Account.ACCOUNT_TYPE_DOMAIN_ADMIN), eq(RoleType.DomainAdmin.getId()), eq(domainId), isNull(String.class),
+                (java.util.Map<String,String>)isNull(), anyString(), anyString(), eq(User.Source.LDAP))).thenReturn(userAccount);
+
+        linkAccountToLdapCmd.execute();
+        LinkAccountToLdapResponse result = (LinkAccountToLdapResponse)linkAccountToLdapCmd.getResponseObject();
+        assertEquals("objectName", linkAccountToLdapCmd.APINAME, result.getObjectName());
+        assertEquals("commandName", linkAccountToLdapCmd.getCommandName(), result.getResponseName());
+        assertEquals("domainId", String.valueOf(domainId), result.getDomainId());
+        assertEquals("type", type, result.getType());
+        assertEquals("name", ldapDomain, result.getLdapDomain());
+        assertEquals("accountId", String.valueOf(accountId), result.getAdminId());
+    }
+}
diff --git a/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LinkDomainToLdapCmdTest.java b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LinkDomainToLdapCmdTest.java
new file mode 100644
index 0000000..8f1fa67
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LinkDomainToLdapCmdTest.java
@@ -0,0 +1,98 @@
+// 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.
+package org.apache.cloudstack.api.command;
+
+import com.cloud.user.Account;
+import com.cloud.user.AccountService;
+import com.cloud.user.User;
+import com.cloud.user.UserAccountVO;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.response.LinkDomainToLdapResponse;
+import org.apache.cloudstack.ldap.LdapManager;
+import org.apache.cloudstack.ldap.LdapUser;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class LinkDomainToLdapCmdTest implements LdapConfigurationChanger
+{
+    @Mock
+    LdapManager ldapManager;
+    @Mock
+    AccountService accountService;
+
+    LinkDomainToLdapCmd linkDomainToLdapCmd;
+
+    @Before
+    public void setUp() throws NoSuchFieldException, IllegalAccessException {
+        linkDomainToLdapCmd = new LinkDomainToLdapCmd();
+        setHiddenField(linkDomainToLdapCmd, "_ldapManager", ldapManager);
+        setHiddenField(linkDomainToLdapCmd, "_accountService", accountService);
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    @Test
+    public void execute() throws Exception {
+//      test with valid params and with admin who doesnt exist in cloudstack
+        Long domainId = 1L;
+        String type = "GROUP";
+        String ldapDomain = "CN=test,DC=ccp,DC=Citrix,DC=com";
+        short accountType = Account.ACCOUNT_TYPE_DOMAIN_ADMIN;
+        String username = "admin";
+        long accountId = 24;
+        setHiddenField(linkDomainToLdapCmd, "ldapDomain", ldapDomain);
+        setHiddenField(linkDomainToLdapCmd, "admin", username);
+        setHiddenField(linkDomainToLdapCmd, "type", type);
+        setHiddenField(linkDomainToLdapCmd, "domainId", domainId);
+        setHiddenField(linkDomainToLdapCmd, "accountType", accountType);
+
+        LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(domainId.toString(), type, ldapDomain, (short)accountType);
+        when(ldapManager.linkDomainToLdap(linkDomainToLdapCmd)).thenReturn(response);
+        when(ldapManager.getUser(username, type, ldapDomain, 1L)).thenReturn(new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", ldapDomain, "ccp", false, null));
+
+        when(accountService.getActiveAccountByName(username, domainId)).thenReturn(null);
+        UserAccountVO userAccount =  new UserAccountVO();
+        userAccount.setAccountId(24);
+        when(accountService.createUserAccount(eq(username), eq(""), eq("Admin"), eq("Admin"), eq("admin@ccp.citrix.com"), isNull(String.class),
+                eq(username), eq(Account.ACCOUNT_TYPE_DOMAIN_ADMIN), eq(RoleType.DomainAdmin.getId()), eq(domainId), isNull(String.class),
+                (java.util.Map<String,String>)isNull(), anyString(), anyString(), eq(User.Source.LDAP))).thenReturn(userAccount);
+
+
+        linkDomainToLdapCmd.execute();
+        LinkDomainToLdapResponse result = (LinkDomainToLdapResponse)linkDomainToLdapCmd.getResponseObject();
+        assertEquals("objectName", "LinkDomainToLdap", result.getObjectName());
+        assertEquals("commandName", linkDomainToLdapCmd.getCommandName(), result.getResponseName());
+        assertEquals("domainId", domainId.toString(), result.getDomainId());
+        assertEquals("type", type, result.getType());
+        assertEquals("name", ldapDomain, result.getLdapDomain());
+        assertEquals("accountId", String.valueOf(accountId), result.getAdminId());
+    }
+
+}
diff --git a/plugins/user-authenticators/ldap/test/org/apache/cloudstack/ldap/LdapConfigurationTest.java b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/ldap/LdapConfigurationTest.java
new file mode 100644
index 0000000..52c70ac
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/ldap/LdapConfigurationTest.java
@@ -0,0 +1,141 @@
+// 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.
+package org.apache.cloudstack.ldap;
+
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.ldap.dao.LdapConfigurationDao;
+import org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(MockitoJUnitRunner.class)
+public class LdapConfigurationTest {
+
+    LdapConfigurationDao ldapConfigurationDao;
+    LdapConfiguration ldapConfiguration;
+
+    private void overrideConfigValue(final String configKeyName, final Object o) throws IllegalAccessException, NoSuchFieldException {
+        Field configKey = LdapConfiguration.class.getDeclaredField(configKeyName);
+        configKey.setAccessible(true);
+
+        ConfigKey key = (ConfigKey)configKey.get(ldapConfiguration);
+
+        Field modifiersField = Field.class.getDeclaredField("modifiers");
+        modifiersField.setAccessible(true);
+        modifiersField.setInt(configKey, configKey.getModifiers() & ~Modifier.FINAL);
+
+        Field f = ConfigKey.class.getDeclaredField("_value");
+        f.setAccessible(true);
+        modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
+        f.set(key, o);
+
+        Field dynamic = ConfigKey.class.getDeclaredField("_isDynamic");
+        dynamic.setAccessible(true);
+        modifiersField.setInt(dynamic, dynamic.getModifiers() & ~Modifier.FINAL);
+        dynamic.setBoolean(key, false);
+    }
+
+    @Before
+    public void init() throws Exception {
+        ldapConfigurationDao =  new LdapConfigurationDaoImpl();
+        ldapConfiguration = new LdapConfiguration(ldapConfigurationDao);;
+    }
+
+    @Test
+    public void getAuthenticationReturnsSimple() throws Exception {
+        overrideConfigValue("ldapBindPrincipal", "cn=bla");
+        overrideConfigValue("ldapBindPassword", "pw");
+        String authentication = ldapConfiguration.getAuthentication(null);
+        assertEquals("authentication should be set to simple", "simple", authentication);
+    }
+
+
+    @Test
+    public void getBaseDnReturnsABaseDn() throws Exception {
+        overrideConfigValue("ldapBaseDn", "dc=cloudstack,dc=org");
+        String baseDn = ldapConfiguration.getBaseDn(null);
+        assertEquals("The set baseDn should be returned","dc=cloudstack,dc=org", baseDn);
+    }
+
+    @Test
+    public void getGroupUniqueMemberAttribute() throws Exception {
+        String [] groupNames = {"bla", "uniquemember", "memberuid", "", null};
+        for (String groupObject: groupNames) {
+            overrideConfigValue("ldapGroupUniqueMemberAttribute", groupObject);
+            String expectedResult = null;
+            if(groupObject == null) {
+                expectedResult = "uniquemember";
+            } else {
+                expectedResult = groupObject;
+            };
+            String result = ldapConfiguration.getGroupUniqueMemberAttribute(null);
+            assertEquals("testing for " + groupObject, expectedResult, result);
+        }
+    }
+
+    @Test
+    public void getSSLStatusCanBeTrue() throws Exception {
+//        given: "We have a ConfigDao with values for truststore and truststore password set"
+        overrideConfigValue("ldapTrustStore", "/tmp/ldap.ts");
+        overrideConfigValue("ldapTrustStorePassword", "password");
+
+        assertTrue("A request is made to get the status of SSL should result in true", ldapConfiguration.getSSLStatus());
+    }
+    @Test
+    public void getSearchGroupPrincipleReturnsSuccessfully() throws Exception {
+        // We have a ConfigDao with a value for ldap.search.group.principle and an LdapConfiguration
+        overrideConfigValue("ldapSearchGroupPrinciple", "cn=cloudstack,cn=users,dc=cloudstack,dc=org");
+        String result = ldapConfiguration.getSearchGroupPrinciple(null);
+
+        assertEquals("The result holds the same value configDao did", "cn=cloudstack,cn=users,dc=cloudstack,dc=org",result);
+    }
+
+    @Test
+    public void  getTrustStorePasswordResopnds() throws Exception {
+        // We have a ConfigDao with a value for truststore password
+        overrideConfigValue("ldapTrustStorePassword", "password");
+
+        String result = ldapConfiguration.getTrustStorePassword();
+
+        assertEquals("The result is password", "password", result);
+    }
+
+
+    @Test
+    public void getGroupObject() throws Exception {
+        String [] groupNames = {"bla", "groupOfUniqueNames", "groupOfNames", "", null};
+        for (String groupObject: groupNames) {
+            overrideConfigValue("ldapGroupObject", groupObject);
+            String expectedResult = null;
+            if(groupObject == null) {
+                expectedResult = "groupOfUniqueNames";
+            } else {
+                expectedResult = groupObject;
+            };
+            String result = ldapConfiguration.getGroupObject(null);
+            assertEquals("testing for " + groupObject, expectedResult, result);
+        }
+    }
+}
\ No newline at end of file
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index a8e24a4..16be9ce 100644
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -39,6 +39,10 @@ import com.cloud.template.TemplateManager;
 import com.cloud.vm.UserVmManager;
 import com.cloud.vm.snapshot.VMSnapshotManager;
 
+/**
+ * @deprecated use the more dynamic ConfigKey
+ */
+@Deprecated
 public enum Config {
 
     // Alert
@@ -1814,42 +1818,6 @@ public enum Config {
                 + "If it is set to -1, then it means always use single-part upload to upload object to S3. ",
             null),
 
-    // Ldap
-    LdapBasedn("Advanced", ManagementServer.class, String.class, "ldap.basedn", null, "Sets the basedn for LDAP", null),
-    LdapBindPassword("Advanced", ManagementServer.class, String.class, "ldap.bind.password", null, "Sets the bind password for LDAP", null),
-    LdapBindPrincipal("Advanced", ManagementServer.class, String.class, "ldap.bind.principal", null, "Sets the bind principal for LDAP", null),
-    LdapEmailAttribute("Advanced", ManagementServer.class, String.class, "ldap.email.attribute", "mail", "Sets the email attribute used within LDAP", null),
-    LdapFirstnameAttribute(
-            "Advanced",
-            ManagementServer.class,
-            String.class,
-            "ldap.firstname.attribute",
-            "givenname",
-            "Sets the firstname attribute used within LDAP",
-            null),
-    LdapLastnameAttribute("Advanced", ManagementServer.class, String.class, "ldap.lastname.attribute", "sn", "Sets the lastname attribute used within LDAP", null),
-    LdapUsernameAttribute("Advanced", ManagementServer.class, String.class, "ldap.username.attribute", "uid", "Sets the username attribute used within LDAP", null),
-    LdapUserObject("Advanced", ManagementServer.class, String.class, "ldap.user.object", "inetOrgPerson", "Sets the object type of users within LDAP", null),
-    LdapSearchGroupPrinciple(
-            "Advanced",
-            ManagementServer.class,
-            String.class,
-            "ldap.search.group.principle",
-            null,
-            "Sets the principle of the group that users must be a member of",
-            null),
-    LdapTrustStore("Advanced", ManagementServer.class, String.class, "ldap.truststore", null, "Sets the path to the truststore to use for SSL", null),
-    LdapTrustStorePassword("Advanced", ManagementServer.class, String.class, "ldap.truststore.password", null, "Sets the password for the truststore", null),
-    LdapGroupObject("Advanced", ManagementServer.class, String.class, "ldap.group.object", "groupOfUniqueNames", "Sets the object type of groups within LDAP", null),
-    LdapGroupUniqueMemberAttribute(
-            "Advanced",
-            ManagementServer.class,
-            String.class,
-            "ldap.group.user.uniquemember",
-            "uniquemember",
-            "Sets the attribute for uniquemembers within a group",
-            null),
-
     // VMSnapshots
     VMSnapshotMax("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a vm", null),
     VMSnapshotCreateWait("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.create.wait", "1800", "In second, timeout for create vm snapshot", null),
@@ -1979,17 +1947,6 @@ public enum Config {
         _scope = ConfigKey.Scope.Global.toString();
     }
 
-    private Config(String category, Class<?> componentClass, Class<?> type, String name, String defaultValue, String description, String range, String scope) {
-        _category = category;
-        _componentClass = componentClass;
-        _type = type;
-        _name = name;
-        _defaultValue = defaultValue;
-        _description = description;
-        _range = range;
-        _scope = scope;
-    }
-
     public String getCategory() {
         return _category;
     }
@@ -2010,10 +1967,6 @@ public enum Config {
         return _type;
     }
 
-    public Class<?> getComponentClass() {
-        return _componentClass;
-    }
-
     public String getScope() {
         return _scope;
     }
@@ -2081,8 +2034,4 @@ public enum Config {
         }
         return categories;
     }
-
-    public static List<Config> getConfigListByScope(String scope) {
-        return s_scopeLevelConfigsMap.get(scope);
-    }
 }
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index c3e9e11..9d9ac52 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -131,8 +131,10 @@ import com.cloud.dc.dao.VlanDao;
 import com.cloud.deploy.DataCenterDeployment;
 import com.cloud.deploy.DeploymentClusterPlanner;
 import com.cloud.domain.Domain;
+import com.cloud.domain.DomainDetailVO;
 import com.cloud.domain.DomainVO;
 import com.cloud.domain.dao.DomainDao;
+import com.cloud.domain.dao.DomainDetailsDao;
 import com.cloud.event.ActionEvent;
 import com.cloud.event.EventTypes;
 import com.cloud.event.UsageEventUtils;
@@ -327,6 +329,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
     @Inject
     AccountDetailsDao _accountDetailsDao;
     @Inject
+    DomainDetailsDao _domainDetailsDao;
+    @Inject
     PrimaryDataStoreDao _storagePoolDao;
     @Inject
     NicSecondaryIpDao _nicSecondaryIpDao;
@@ -548,6 +552,21 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
                 _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);
+                }
+                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");
             }
@@ -655,6 +674,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
         final Long storagepoolId = cmd.getStoragepoolId();
         final Long accountId = cmd.getAccountId();
         final Long imageStoreId = cmd.getImageStoreId();
+        final Long domainId = cmd.getDomainId();
         CallContext.current().setEventDetails(" Name: " + name + " New Value: " + (name.toLowerCase().contains("password") ? "*****" : value == null ? "" : value));
         // check if config value exists
         final ConfigurationVO config = _configDao.findByName(name);
@@ -700,6 +720,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
             id = accountId;
             paramCountCheck++;
         }
+        if (domainId != null) {
+            scope = ConfigKey.Scope.Domain.toString();
+            id = domainId;
+            paramCountCheck++;
+        }
         if (storagepoolId != null) {
             scope = ConfigKey.Scope.StoragePool.toString();
             id = storagepoolId;
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index c855c34..82a3752 100644
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -1686,6 +1686,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         final Long clusterId = cmd.getClusterId();
         final Long storagepoolId = cmd.getStoragepoolId();
         final Long accountId = cmd.getAccountId();
+        final Long domainId = cmd.getDomainId();
         final Long imageStoreId = cmd.getImageStoreId();
         String scope = null;
         Long id = null;
@@ -1706,6 +1707,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
             id = accountId;
             paramCountCheck++;
         }
+        if (domainId != null) {
+            scope = ConfigKey.Scope.Domain.toString();
+            id = domainId;
+            paramCountCheck++;
+        }
         if (storagepoolId != null) {
             scope = ConfigKey.Scope.StoragePool.toString();
             id = storagepoolId;
diff --git a/server/src/com/cloud/user/AccountManager.java b/server/src/com/cloud/user/AccountManager.java
index e0e7d3b..e708b04 100644
--- a/server/src/com/cloud/user/AccountManager.java
+++ b/server/src/com/cloud/user/AccountManager.java
@@ -215,4 +215,6 @@ public interface AccountManager extends AccountService, Configurable{
             "false",
             "This parameter allows the users to enable or disable of showing secret key as a part of response for various APIs. By default it is set to false.",
             true);
+
+    boolean moveUser(long id, Long domainId, long accountId);
 }
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index fea8b47..dc9fdc0 100644
--- a/server/src/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/com/cloud/user/AccountManagerImpl.java
@@ -1702,17 +1702,32 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
 
     @ActionEvent(eventType = EventTypes.EVENT_USER_MOVE, eventDescription = "moving User to a new account")
     public boolean moveUser(MoveUserCmd cmd) {
-        UserVO user = getValidUserVO(cmd.getId());
+        final Long id = cmd.getId();
+        UserVO user = getValidUserVO(id);
         Account oldAccount = _accountDao.findById(user.getAccountId());
         checkAccountAndAccess(user, oldAccount);
         long domainId = oldAccount.getDomainId();
 
-        long newAccountId = getNewAccountId(cmd, domainId);
+        long newAccountId = getNewAccountId(domainId, cmd.getAccountName(), cmd.getAccountId());
 
+        return moveUser(user, newAccountId);
+    }
+
+    public boolean moveUser(long id, Long domainId, long accountId) {
+        UserVO user = getValidUserVO(id);
+        Account oldAccount = _accountDao.findById(user.getAccountId());
+        checkAccountAndAccess(user, oldAccount);
+        Account newAccount = _accountDao.findById(accountId);
+        checkIfNotMovingAcrossDomains(domainId, newAccount);
+        return moveUser(user , accountId);
+    }
+
+    private boolean moveUser(UserVO user, long newAccountId) {
         if(newAccountId == user.getAccountId()) {
             // could do a not silent fail but the objective of the user is reached
             return true; // no need to create a new user object for this user
         }
+
         return Transaction.execute(new TransactionCallback<Boolean>() {
             @Override
             public Boolean doInTransaction(TransactionStatus status) {
@@ -1721,34 +1736,37 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
                 user.setUuid(UUID.randomUUID().toString());
                 _userDao.update(user.getId(),user);
                 newUser.setAccountId(newAccountId);
-                boolean success = _userDao.remove(cmd.getId());
+                boolean success = _userDao.remove(user.getId());
                 UserVO persisted = _userDao.persist(newUser);
                 return success && persisted.getUuid().equals(user.getExternalEntity());
             }
         });
     }
 
-    private long getNewAccountId(MoveUserCmd cmd, long domainId) {
+    private long getNewAccountId(long domainId, String accountName, Long accountId) {
         Account newAccount = null;
-        if (StringUtils.isNotBlank(cmd.getAccountName())) {
+        if (StringUtils.isNotBlank(accountName)) {
             if(s_logger.isDebugEnabled()) {
-                s_logger.debug("Getting id for account by name '" + cmd.getAccountName() + "' in domain " + domainId);
+                s_logger.debug("Getting id for account by name '" + accountName + "' in domain " + domainId);
             }
-            newAccount = _accountDao.findEnabledAccount(cmd.getAccountName(), domainId);
+            newAccount = _accountDao.findEnabledAccount(accountName, domainId);
         }
-        if (newAccount == null && cmd.getAccountId() != null) {
-            newAccount = _accountDao.findById(cmd.getAccountId());
+        if (newAccount == null && accountId != null) {
+            newAccount = _accountDao.findById(accountId);
         }
         if (newAccount == null) {
             throw new CloudRuntimeException("no account name or account id. this should have been caught before this point");
         }
-        long newAccountId = newAccount.getAccountId();
 
+        checkIfNotMovingAcrossDomains(domainId, newAccount);
+        return newAccount.getAccountId();
+    }
+
+    private void checkIfNotMovingAcrossDomains(long domainId, Account newAccount) {
         if(newAccount.getDomainId() != domainId) {
             // not in scope
             throw new InvalidParameterValueException("moving a user from an account in one domain to an account in annother domain is not supported!");
         }
-        return newAccountId;
     }
 
     private void checkAccountAndAccess(UserVO user, Account account) {
diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java
index 8ea0473..0a92c14 100644
--- a/server/test/com/cloud/user/MockAccountManagerImpl.java
+++ b/server/test/com/cloud/user/MockAccountManagerImpl.java
@@ -123,7 +123,13 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco
         return false;
     }
 
-    @Override public boolean moveUser(MoveUserCmd moveUserCmd) {
+    @Override
+    public boolean moveUser(MoveUserCmd moveUserCmd) {
+        return false;
+    }
+
+    @Override
+    public boolean moveUser(long id, Long domainId, long accountId) {
         return false;
     }
 
diff --git a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java
index 92d421c..3ffec4c 100644
--- a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java
+++ b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java
@@ -19,34 +19,6 @@ package org.apache.cloudstack.networkoffering;
 
 import java.io.IOException;
 
-import com.cloud.network.dao.FirewallRulesDcidrsDaoImpl;
-import com.cloud.storage.StorageManager;
-import org.mockito.Mockito;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.ComponentScan.Filter;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.FilterType;
-import org.springframework.core.type.classreading.MetadataReader;
-import org.springframework.core.type.classreading.MetadataReaderFactory;
-import org.springframework.core.type.filter.TypeFilter;
-
-import org.apache.cloudstack.acl.SecurityChecker;
-import org.apache.cloudstack.affinity.AffinityGroupService;
-import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
-import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-import org.apache.cloudstack.framework.config.ConfigDepot;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.cloudstack.region.PortableIpDaoImpl;
-import org.apache.cloudstack.region.PortableIpRangeDaoImpl;
-import org.apache.cloudstack.region.dao.RegionDaoImpl;
-import org.apache.cloudstack.storage.datastore.db.ImageStoreDaoImpl;
-import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDaoImpl;
-import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl;
-import org.apache.cloudstack.test.utils.SpringUtils;
-
 import com.cloud.agent.AgentManager;
 import com.cloud.alert.AlertManager;
 import com.cloud.api.query.dao.UserAccountJoinDaoImpl;
@@ -67,6 +39,7 @@ import com.cloud.dc.dao.PodVlanDaoImpl;
 import com.cloud.dc.dao.PodVlanMapDaoImpl;
 import com.cloud.dc.dao.VlanDaoImpl;
 import com.cloud.domain.dao.DomainDaoImpl;
+import com.cloud.domain.dao.DomainDetailsDao;
 import com.cloud.event.dao.UsageEventDaoImpl;
 import com.cloud.host.dao.HostDaoImpl;
 import com.cloud.host.dao.HostDetailsDaoImpl;
@@ -79,6 +52,7 @@ import com.cloud.network.StorageNetworkManager;
 import com.cloud.network.dao.AccountGuestVlanMapDaoImpl;
 import com.cloud.network.dao.FirewallRulesCidrsDaoImpl;
 import com.cloud.network.dao.FirewallRulesDaoImpl;
+import com.cloud.network.dao.FirewallRulesDcidrsDaoImpl;
 import com.cloud.network.dao.IPAddressDaoImpl;
 import com.cloud.network.dao.LoadBalancerDaoImpl;
 import com.cloud.network.dao.NetworkDao;
@@ -107,6 +81,7 @@ import com.cloud.server.ConfigurationServer;
 import com.cloud.server.ManagementService;
 import com.cloud.service.dao.ServiceOfferingDaoImpl;
 import com.cloud.service.dao.ServiceOfferingDetailsDaoImpl;
+import com.cloud.storage.StorageManager;
 import com.cloud.storage.dao.DiskOfferingDaoImpl;
 import com.cloud.storage.dao.SnapshotDaoImpl;
 import com.cloud.storage.dao.StoragePoolDetailsDaoImpl;
@@ -123,6 +98,30 @@ import com.cloud.vm.dao.NicDaoImpl;
 import com.cloud.vm.dao.NicSecondaryIpDaoImpl;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.VMInstanceDaoImpl;
+import org.apache.cloudstack.acl.SecurityChecker;
+import org.apache.cloudstack.affinity.AffinityGroupService;
+import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import org.apache.cloudstack.framework.config.ConfigDepot;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.region.PortableIpDaoImpl;
+import org.apache.cloudstack.region.PortableIpRangeDaoImpl;
+import org.apache.cloudstack.region.dao.RegionDaoImpl;
+import org.apache.cloudstack.storage.datastore.db.ImageStoreDaoImpl;
+import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDaoImpl;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl;
+import org.apache.cloudstack.test.utils.SpringUtils;
+import org.mockito.Mockito;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.ComponentScan.Filter;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.filter.TypeFilter;
 
 @Configuration
 @ComponentScan(basePackageClasses = {AccountVlanMapDaoImpl.class, DomainVlanMapDaoImpl.class, VolumeDaoImpl.class, HostPodDaoImpl.class, DomainDaoImpl.class, ServiceOfferingDaoImpl.class,
@@ -321,6 +320,11 @@ public class
     }
 
     @Bean
+    public DomainDetailsDao domainDetailsDao() {
+        return Mockito.mock(DomainDetailsDao.class);
+    }
+
+    @Bean
     public DataStoreManager dataStoreManager() {
         return Mockito.mock(DataStoreManager.class);
     }
diff --git a/ui/scripts/domains.js b/ui/scripts/domains.js
index 704195e..1f65ff4 100644
--- a/ui/scripts/domains.js
+++ b/ui/scripts/domains.js
@@ -457,6 +457,15 @@
                         }
                     }
                 },
+
+                tabFilter: function(args) {
+                    var hiddenTabs = [];
+                    if(!isAdmin()) {
+                        hiddenTabs.push('settings');
+                    }
+                    return hiddenTabs;
+                },
+
                 tabs: {
                     details: {
                         title: 'label.details',
@@ -638,36 +647,6 @@
                             domainObj["vmTotal"] = totalVMs;
                             domainObj["volumeTotal"] = totalVolumes;
 
-                            /* $.ajax({
-                url: createURL("listVirtualMachines&details=min&domainid=" + domainObj.id),
-                async: false,
-                dataType: "json",
-                success: function(json) {
-                  var items = json.listvirtualmachinesresponse.virtualmachine;
-                  var total;
-                  if (items != null)
-                    total = items.length;
-                  else
-                    total = 0;
-                  domainObj["vmTotal"] = total;
-                }
-              });
-
-              $.ajax({
-                url: createURL("listVolumes&domainid=" + domainObj.id),
-                async: false,
-                dataType: "json",
-                success: function(json) {
-                  var items = json.listvolumesresponse.volume;
-                  var total;
-                  if (items != null)
-                    total = items.length;
-                  else
-                    total = 0;
-                  domainObj["volumeTotal"] = total;
-                }
-              });*/
-
                             $.ajax({
                                 url: createURL("listResourceLimits&domainid=" + domainObj.id),
                                 async: false,
@@ -722,7 +701,58 @@
                                 actionFilter: domainActionfilter
                             });
                         }
+                    },
+                    // Granular settings for domains
+                    settings: {
+                        title: 'label.settings',
+                        custom: cloudStack.uiCustom.granularSettings({
+                            dataProvider: function(args) {
+                                $.ajax({
+                                    url: createURL('listConfigurations&domainid=' + args.context.domains[0].id),
+                                    data: listViewDataProvider(args, {}, { searchBy: 'name' }),
+                                    success: function(json) {
+                                        args.response.success({
+                                            data: json.listconfigurationsresponse.configuration
+                                        });
+
+                                    },
+
+                                    error: function(json) {
+                                        args.response.error(parseXMLHttpResponse(json));
+
+                                    }
+                                });
+
+                            },
+                            actions: {
+                                edit: function(args) {
+                                    // call updateDomainLevelParameters
+                                    var data = {
+                                        name: args.data.jsonObj.name,
+                                        value: args.data.value
+                                    };
+
+                                    $.ajax({
+                                        url: createURL('updateConfiguration&domainid=' + args.context.domains[0].id),
+                                        data: data,
+                                        success: function(json) {
+                                            var item = json.updateconfigurationresponse.configuration;
+                                            args.response.success({
+                                                data: item
+                                            });
+                                        },
+
+                                        error: function(json) {
+                                            args.response.error(parseXMLHttpResponse(json));
+                                        }
+
+                                    });
+
+                                }
+                            }
+                        })
                     }
+
                 }
             },
             labelField: 'name',

-- 
To stop receiving notification emails like this one, please contact
['"commits@cloudstack.apache.org" <co...@cloudstack.apache.org>'].