You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2018/01/02 10:38:45 UTC

[GitHub] DaanHoogland closed pull request #2369: CLOUDSTACK-10117 Domain level ldap configuration

DaanHoogland closed pull request #2369: CLOUDSTACK-10117 Domain level ldap configuration
URL: https://github.com/apache/cloudstack/pull/2369
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 0e275b5de15..41cf7d98553 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -707,6 +707,7 @@
 
     public static final String HAS_ANNOTATION = "hasannotation";
     public static final String LAST_ANNOTATED = "lastannotated";
+    public static final String LDAP_DOMAIN = "ldapdomain";
 
 
     public enum HostDetails {
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 8f71f48470e..80ebaf43f64 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 @@
 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 @@
                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 Long getAccountId() {
         return accountId;
     }
 
+    public Long getDomainId() {
+        return domainId;
+    }
+
     public Long getImageStoreId() {
         return imageStoreId;
     }
@@ -158,6 +169,9 @@ public void execute() {
             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 fa5e26e418f..936f0cd69f1 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 @@
 
 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 @@
                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 Long getAccountId() {
         return accountId;
     }
 
+    public Long getDomainId() {
+        return domainId;
+    }
+
     public Long getImageStoreId() {
         return imageStoreId;
     }
@@ -157,6 +168,9 @@ public void execute() {
             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 8a0d7cdde5c..84c27583925 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 5d51b47a994..6fe771c4b81 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',
@@ -516,3 +516,15 @@ UPDATE `cloud`.`vm_template` SET guest_os_id=99 WHERE id=8;
 
 -- Network External Ids
 ALTER TABLE `cloud`.`networks` ADD `external_id` varchar(255);
+
+-- 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;
diff --git a/engine/schema/src/com/cloud/domain/DomainDetailVO.java b/engine/schema/src/com/cloud/domain/DomainDetailVO.java
new file mode 100644
index 00000000000..61eb6cfd28e
--- /dev/null
+++ b/engine/schema/src/com/cloud/domain/DomainDetailVO.java
@@ -0,0 +1,76 @@
+// 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;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+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 = "domain_details")
+public class DomainDetailVO implements InternalIdentity {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private long id;
+
+    @Column(name = "domain_id")
+    private long domainId;
+
+    @Column(name = "name")
+    private String name;
+
+    @Encrypt
+    @Column(name = "value")
+    private String value;
+
+    protected DomainDetailVO() {
+    }
+
+    public DomainDetailVO(long domainId, String name, String value) {
+        this.domainId = domainId;
+        this.name = name;
+        this.value = value;
+    }
+
+    public long getDomainId() {
+        return domainId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+}
diff --git a/engine/schema/src/com/cloud/domain/dao/DomainDetailsDao.java b/engine/schema/src/com/cloud/domain/dao/DomainDetailsDao.java
new file mode 100644
index 00000000000..51362cf885e
--- /dev/null
+++ b/engine/schema/src/com/cloud/domain/dao/DomainDetailsDao.java
@@ -0,0 +1,34 @@
+// 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.Map;
+
+import com.cloud.domain.DomainDetailVO;
+import com.cloud.utils.db.GenericDao;
+
+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);
+
+    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 00000000000..ad7f7040207
--- /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 fb2a57b71f6..1734b98757b 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 @@
 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 e68fd3cdae3..6a85b90b70d 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 ConfigDepotImpl() {
         _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 7f1d5b805a8..4105a617e6c 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.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.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.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 @@
     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/user-authenticators/ldap/pom.xml b/plugins/user-authenticators/ldap/pom.xml
index 9f97f08f3fd..e2b0ead17e0 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 a138e7ddd4a..cfef21e2aff 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 @@
  * @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 void execute() throws ResourceUnavailableException, InsufficientCapacityE
 
             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 @@ private LDAPConfigResponse createLDAPConfigResponse(String hostname, Integer por
     }
 
     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 eb3729d9d9e..0a4dc20ee0b 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 @@
  * @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 @@ private boolean removeLDAP() {
         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 555d1a987fd..7c592888364 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 @@
 
 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 @@
     @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 LdapAddConfigurationCmd(final LdapManager ldapManager) {
     @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 int getPort() {
         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 d845857925d..826375756ed 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
@@ -136,10 +136,11 @@ public void execute() throws ServerApiException {
         }
         final CallContext callContext = getCurrentContext();
         String finalAccountName = getAccountName();
+        // TODO add domain id to create account and create user calls
         Long finalDomainId = getDomainId();
         callContext.setEventDetails("Account Name: " + finalAccountName + ", Domain Id:" + finalDomainId);
         try {
-            final LdapUser user = _ldapManager.getUser(username);
+            final LdapUser user = _ldapManager.getUser(username, null);
             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 30b37d8b88d..3ffebecfb95 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 @@
 
 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 @@
     @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 LdapDeleteConfigurationCmd(final LdapManager ldapManager) {
         _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 9fdd700638c..564c1d0a1ef 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 void execute() throws ResourceUnavailableException, InsufficientCapacityE
         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 050fb36cb19..db6318e6b2c 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 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 @@
     @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 int getPort() {
         return port;
     }
 
+    public Long getDomainId() {
+        return domainId;
+    }
+
     public void setHostname(final String hostname) {
         this.hostname = hostname;
     }
@@ -104,4 +113,8 @@ public void setHostname(final String hostname) {
     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 e655f5f4ac0..b2266dc8fd3 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 void execute() throws ServerApiException {
         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/LinkDomainToLdapCmd.java
index 477e80f2556..00140952051 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 @@
     @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 @@
     @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 a4e47828844..5d831fd2e0a 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
@@ -21,7 +21,10 @@
 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")
@@ -31,18 +34,27 @@
     @Param(description = "port")
     private int port;
 
+    @SerializedName("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 +72,12 @@ public void setHostname(final String hostname) {
     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/LinkDomainToLdapResponse.java
index b0032b04b4d..ab41d11f3c2 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
@@ -29,10 +29,15 @@
     @Param(description = "id of the Domain which is linked to LDAP")
     private long 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;
+
     @SerializedName(ApiConstants.TYPE)
     @Param(description = "type of the name in LDAP which is linke to the domain")
     private String type;
@@ -45,9 +50,10 @@
     @Param(description = "Domain Admin accountId that is created")
     private String adminId;
 
-    public LinkDomainToLdapResponse(long domainId, String type, String name, short accountType) {
+    public LinkDomainToLdapResponse(long domainId, String type, String ldapDomain, short accountType) {
         this.domainId = domainId;
-        this.name = name;
+        this.name = ldapDomain;
+        this.ldapDomain = ldapDomain;
         this.type = type;
         this.accountType = accountType;
     }
@@ -56,8 +62,8 @@ public long getDomainId() {
         return domainId;
     }
 
-    public String getName() {
-        return name;
+    public String getLdapDomain() {
+        return ldapDomain == null ? name : ldapDomain;
     }
 
     public String getType() {
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 0df638ad228..e844df57c1c 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 @@
     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 @@ protected boolean isUserDisabled(SearchResult result) throws NamingException {
         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 add39c5b13d..bfca71cc7d4 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
@@ -70,9 +70,9 @@ public LdapAuthenticator(final LdapManager ldapManager, final UserAccountDao use
             LdapTrustMapVO ldapTrustMapVO = _ldapManager.getDomainLinkedToLdap(domainId);
             if(ldapTrustMapVO != null) {
                 try {
-                    LdapUser ldapUser = _ldapManager.getUser(username, ldapTrustMapVO.getType().toString(), ldapTrustMapVO.getName());
+                    LdapUser ldapUser = _ldapManager.getUser(username, ldapTrustMapVO.getType().toString(), ldapTrustMapVO.getName(), domainId);
                     if(!ldapUser.isDisabled()) {
-                        result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password);
+                        result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password, domainId);
                         if(result) {
                             if(user == null) {
                                 // import user to cloudstack
@@ -93,9 +93,9 @@ public LdapAuthenticator(final LdapManager ldapManager, final UserAccountDao use
                 //domain is not linked to ldap follow normal authentication
                 if(user != null ) {
                     try {
-                        LdapUser ldapUser = _ldapManager.getUser(username);
+                        LdapUser ldapUser = _ldapManager.getUser(username, domainId);
                         if(!ldapUser.isDisabled()) {
-                            result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password);
+                            result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password, domainId);
                         } else {
                             s_logger.debug("user with principal "+ ldapUser.getPrincipal() + " is disabled in ldap");
                         }
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 56b39a8b3d1..2a662a74648 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 @@
 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,8 +250,13 @@ public String getProviderUrl() {
         return providerUrls.toString();
     }
 
-    public String[] getReturnAttributes() {
-        return new String[] {getUsernameAttribute(), getEmailAttribute(), getFirstnameAttribute(), getLastnameAttribute(), getCommonNameAttribute(),
+    public String[] getReturnAttributes(final Long domainId) {
+        return new String[] {
+                getUsernameAttribute(domainId),
+                getEmailAttribute(domainId),
+                getFirstnameAttribute(domainId),
+                getLastnameAttribute(domainId),
+                getCommonNameAttribute(),
                 getUserAccountControlAttribute()};
     }
 
@@ -119,8 +264,8 @@ 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 +277,51 @@ public boolean getSSLStatus() {
     }
 
     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 +329,12 @@ public Integer getLdapPageSize() {
         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 +344,25 @@ public String getConfigComponentName() {
 
     @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 488e7f44485..e7db88675ab 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 @@
     @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 int getPort() {
         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 9e27fff078e..b141f053008 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 LdapContextFactory(final LdapConfiguration ldapConfiguration) {
         _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 @@ private void enableSSL(final Hashtable<String, String> environment) {
         }
     }
 
-    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 @@ private void enableSSL(final Hashtable<String, String> environment) {
         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 6af2c4ebd95..2dafd0461aa 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,7 +18,10 @@
 
 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.LinkDomainToLdapCmd;
 import org.apache.cloudstack.api.response.LdapConfigurationResponse;
 import org.apache.cloudstack.api.response.LdapUserResponse;
 
@@ -31,23 +34,30 @@
 
     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 +65,7 @@
 
     List<LdapUser> searchUsers(String query) throws NoLdapUserMatchingQueryException;
 
-    LinkDomainToLdapResponse linkDomainToLdap(Long domainId, String type, String name, short accountType);
+    LinkDomainToLdapResponse linkDomainToLdap(LinkDomainToLdapCmd cmd);
 
-    public LdapTrustMapVO getDomainLinkedToLdap(long domainId);
+    LdapTrustMapVO getDomainLinkedToLdap(long domainId);
 }
\ 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 a4d340647f4..36f5f545d55 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
@@ -24,6 +24,8 @@
 import javax.naming.NamingException;
 import javax.naming.ldap.LdapContext;
 
+import com.cloud.domain.dao.DomainDao;
+
 import org.apache.cloudstack.api.LdapValidator;
 import org.apache.cloudstack.api.command.LDAPConfigCmd;
 import org.apache.cloudstack.api.command.LDAPRemoveCmd;
@@ -54,6 +56,9 @@
     @Inject
     private LdapConfigurationDao _ldapConfigurationDao;
 
+    @Inject
+    private DomainDao domainDao;
+
     @Inject
     private LdapContextFactory _ldapContextFactory;
 
@@ -80,17 +85,32 @@ public LdapManagerImpl(final LdapConfigurationDao ldapConfigurationDao, final Ld
     }
 
     @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");
@@ -102,10 +122,18 @@ public LdapConfigurationResponse addConfiguration(final String hostname, final i
         }
     }
 
+    /**
+     * 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) {
@@ -127,10 +155,11 @@ private void closeContext(final LdapContext context) {
 
     @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
@@ -146,14 +175,23 @@ public LdapUserResponse createLdapUserResponse(final LdapUser user) {
     }
 
     @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);
         }
     }
 
@@ -174,13 +212,13 @@ public LdapConfigurationResponse deleteConfiguration(final String hostname) thro
     }
 
     @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);
@@ -191,26 +229,26 @@ public LdapUser getUser(final String username) throws NoLdapUserMatchingQueryExc
     }
 
     @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("*");
@@ -220,11 +258,11 @@ public LdapUser getUser(final String username, final String type, final String n
     }
 
     @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);
@@ -242,7 +280,8 @@ public boolean isLdapEnabled() {
     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());
     }
 
@@ -250,9 +289,10 @@ public boolean isLdapEnabled() {
     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);
@@ -262,7 +302,13 @@ public boolean isLdapEnabled() {
     }
 
     @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");
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 4e2bcf816b2..c9fcaa23cc0 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 @@
         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/OpenLdapUserManagerImpl.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/OpenLdapUserManagerImpl.java
index 0c3e0d71705..7a00dc8cb38 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,17 +50,17 @@ public OpenLdapUserManagerImpl(final LdapConfiguration ldapConfiguration) {
         _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();
 
         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);
@@ -68,23 +68,27 @@ protected LdapUser createUser(final SearchResult result) throws NamingException
         return new LdapUser(username, email, firstname, lastname, principal, domain, disabled);
     }
 
-    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 +102,10 @@ private String generateSearchFilter(final String username) {
         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 +125,8 @@ private String generateGroupSearchFilter(final String groupName) {
     }
 
     @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 +135,29 @@ public LdapUser getUser(final String username, final LdapContext context) throws
     }
 
     @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 +169,21 @@ public LdapUser getUser(final String username, final String type, final String n
         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 +192,13 @@ protected String getMemberOfAttribute() {
     }
 
     @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 +209,7 @@ protected String getMemberOfAttribute() {
             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 +221,42 @@ protected String getMemberOfAttribute() {
         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 +267,28 @@ public LdapUser searchUser(final String basedn, final String searchString, final
     }
 
     @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 a2d5e65248e..e99c78be9b7 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 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 8125f8cd2de..fa4c0af236f 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 @@
 @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 LdapConfigurationDaoImpl() {
         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 LdapConfigurationVO findByHostname(final String hostname) {
     }
 
     @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/test/groovy/org/apache/cloudstack/ldap/ADLdapUserManagerImplSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/ADLdapUserManagerImplSpec.groovy
index 93b1b17a460..4b631b44e3b 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 ca19e8c633b..cb091447ce5 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()
@@ -174,7 +174,7 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
         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.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)
 
@@ -207,7 +207,7 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
         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.canAuthenticate(_, _, _) >> true
         //user should be enabled in cloudstack if disabled
         accountManager.enableUser(1) >> userAccount
 
@@ -238,7 +238,7 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
         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.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 144890957f2..e94b0d40fb4 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 6f967cc6d8b..ec84d38e125 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 15408833a65..eead0bcd28c 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 a0b20bbcb13..e081b503caa 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
@@ -35,35 +35,6 @@ import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
 import javax.naming.NamingException
 
 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)
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 31d56ef68cb..caa524701b2 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 434151ae234..af0495c4059 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
 
@@ -55,7 +53,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         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
+        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]
@@ -83,7 +81,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         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
+        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]
@@ -112,7 +110,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         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
+        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]
@@ -141,7 +139,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         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
+        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]
@@ -205,7 +203,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         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
+        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
 
@@ -235,7 +233,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         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
+        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
 
@@ -264,7 +262,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
         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
+        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 5247a1ec895..55de85cd7e7 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"
@@ -54,7 +54,7 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
 		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
+		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)
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 c9af0020848..619f486f71c 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
     }
@@ -140,7 +140,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         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)
         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
@@ -428,7 +428,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
         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;
     }
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 9d667bf4cfb..f32a419867f 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
@@ -128,40 +128,6 @@ class LinkDomainToLdapCmdSpec extends Specification {
         result.getAdminId() == null
     }
 
-    def "test with valid params and with admin who doesnt exist in cloudstack"() {
-        def domainId = 1;
-        def type = "GROUP";
-        def name = "CN=test,DC=ccp,DC=Citrix,DC=com"
-        def accountType = 2;
-        def username = "admin"
-        def accountId = 24
-
-        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", false)
-
-        _accountService.getActiveAccountByName(username, domainId) >> null
-        UserAccount userAccount = Mock(UserAccount)
-        userAccount.getAccountId() >> 24
-        _accountService.createUserAccount(username, "", "Admin", "Admin", "admin@ccp.citrix.com", null, username, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, domainId,
-                username, null, _, _, User.Source.LDAP) >> userAccount
-
-        linkDomainToLdapCmd.admin = username
-        linkDomainToLdapCmd.type = type
-        linkDomainToLdapCmd.name = name
-        linkDomainToLdapCmd.domainId = domainId
-
-        when:
-        linkDomainToLdapCmd.execute()
-        then:
-        LinkDomainToLdapResponse result = (LinkDomainToLdapResponse)linkDomainToLdapCmd.getResponseObject()
-        result.getObjectName() == "LinkDomainToLdap"
-        result.getResponseName() == linkDomainToLdapCmd.getCommandName()
-        result.getDomainId() == domainId
-        result.getType() == type
-        result.getName() == name
-        result.getAdminId() == String.valueOf(accountId)
-    }
 
     def "test when admin doesnt exist in ldap"() {
         def domainId = 1;
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 cb08c8fd47c..40daa4110fc 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 00000000000..61aa959e81a
--- /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 00000000000..1765fc5c56c
--- /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);
+        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 00000000000..b1bce6f70c4
--- /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));
+        users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false));
+        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/LinkDomainToLdapCmdTest.java b/plugins/user-authenticators/ldap/test/org/apache/cloudstack/api/command/LinkDomainToLdapCmdTest.java
new file mode 100644
index 00000000000..7d28349e3cc
--- /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 = 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;
+        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, 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));
+
+        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, 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 00000000000..52c70ac0d19
--- /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 bc8272a1b79..d4404e15597 100644
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -39,6 +39,10 @@
 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 @@
                 + "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 @@ private Config(String category, Class<?> componentClass, Class<?> type, String n
         _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 String getDefaultValue() {
         return _type;
     }
 
-    public Class<?> getComponentClass() {
-        return _componentClass;
-    }
-
     public String getScope() {
         return _scope;
     }
@@ -2081,8 +2034,4 @@ public static Config getConfig(String name) {
         }
         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 dfc7c372d48..9a78d73a46e 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -130,8 +130,10 @@
 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;
@@ -326,6 +328,8 @@
     @Inject
     AccountDetailsDao _accountDetailsDao;
     @Inject
+    DomainDetailsDao _domainDetailsDao;
+    @Inject
     PrimaryDataStoreDao _storagePoolDao;
     @Inject
     NicSecondaryIpDao _nicSecondaryIpDao;
@@ -544,6 +548,21 @@ public String updateConfiguration(final long userId, final String name, final St
                 _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");
             }
@@ -651,6 +670,7 @@ public Configuration updateConfiguration(final UpdateCfgCmd cmd) throws InvalidP
         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);
@@ -696,6 +716,11 @@ public Configuration updateConfiguration(final UpdateCfgCmd cmd) throws InvalidP
             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 c855c34b60f..82a37529b25 100644
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -1686,6 +1686,7 @@ private boolean hasSuitablePoolsForVolume(final VolumeVO volume, final Host host
         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 @@ private boolean hasSuitablePoolsForVolume(final VolumeVO volume, final Host host
             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/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java
index 92d421c0efb..3ffec4cd020 100644
--- a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java
+++ b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java
@@ -19,34 +19,6 @@
 
 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.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.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.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.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,
@@ -320,6 +319,11 @@ public AccountDetailsDao accountDetailsDao() {
         return Mockito.mock(AccountDetailsDao.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 704195e08a9..1f65ff4bdae 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',


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services