Windows Server 2008 AD LDS Load Testing using ADTEST - Part 1
ADTest (http://www.microsoft.com/downloads/en/details.aspx?familyid=4814FE3F-92CE-4871-B8A4-99F98B3F4338&displaylang=en) is the LDAP load testing tool to simulate client transaction, it was released few years back (2003). To perform the load testing for Windows 2008 AD LDS, ADTest is the recommended tool (it is the only free LDAP load testing tool that I know – please update this article if there is other (free) tools…).
Another good resource which discusses the usage the ADTest is Active Directory Performance for 64-bit Versions of Windows Server 2003 (http://www.microsoft.com/downloads/en/details.aspx?FamilyID=52e7c3bd-570a-475c-96e0-316dc821e3e7&displaylang=en) whitepaper.
This document consists of 2 part, part 1 and part 2, and structured into the following steps:
- Plan the test (how many users, directory structures, LDAP operations test)
- Install and configure AD LDS
- Install and configure ADTest
- Create test source file
- Build directory structures
- Create users and groups (include populating users to group)
- LDAP operations test
The second part of this document can be found at http://social.technet.microsoft.com/wiki/contents/articles/windows-2008-ad-lds-load-testing-using-adtest-part-2.aspx
Plan the Test
In this initial step, agree with the stakeholder on the load testing scenarios, like:
- How many users: this is the baseline number of load testing, unlike Active Directory; in the case of AD LDS computer objects may not significant factor.
- Directory structures: Agree on the directory structures with stakeholder, so it can emulate the production directory structures
- LDAP Operations Test:
- Authentications: NTLM, Kerberos and LDAP Bind
- Create objects: Users and Groups
- Search attribute(s)
- Update attribute(s)
- Required infrastructure: which include the Active Directory, AD LDS and client machine
Install and Configure AD LDS
To install and configure AD LDS for testing, you need to install the Active Directory Lightweight Directory Services role from the Windows 2008 Server Manager.
After the AD LDS role is installed, then AD LDS instance need to be created. Steps for creating the AD LDS instance can be found here: http://technet.microsoft.com/en-us/library/cc770623.aspx
It is recommended to have the following settings:
- Name instance like AD domain name, if your AD called fabrikam.com, then the AD LDS application partition name can be called dc=fabrikam,dc=corp, this is due to ADTest try to get the first DN section dc=fabrikam for the user who run the ADTest tool authentication.
In my testing environment, I have a domain called fabrikam.com then I have AD LDS partition called dc=liteware,dc=corp, and run the AD LDS remotely (from Windows 7 client). The following error occurred:
The workaround of this issue is to create the AD LDS partition using the DC=fabrikam,DC=corp.
- Create a domain user account and include it as a member of the Administrators group in the configuration partition, this user will run the ADTest
- For the testing purpose, AD LDS can be excluded from Domain or Local password policies, set the ADAMDisablePasswordPolicies to 1.
Install and Configure ADTest
You can prepare a workstation, and download then install ADTest from http://www.microsoft.com/downloads/en/details.aspx?familyid=4814FE3F-92CE-4871-B8A4-99F98B3F4338&displaylang=en.
The installation process is straight forward. ADTest will be installed in C:\Program Files\Windows Resource Kits\Tools by default.
Create Test File
The ADTest installation provides the test file called adtest.ats, this file is the text file with all the tests definition. For AD LDS we need to tweak the test file to suit AD LDS testing.
I based my test file from ADTest is Active Directory Performance for 64-bit Versions of Windows Server 2003 whitepaper.
---start test file---
//---------------- DEFINES ------------------------//
// [ROOT] is specified on the command line (e.g. -r 32 for [ROOT] = 32)
//Number of users in an organization unit
//this is the default defined range
#define $DefaultRange #(0-2000)
#define $GroupRange #(0-50)
//Users are formatted u0001_0001
#define $Padding ######
#define $UserName u##([ROOT])_$Padding(*)
//Organization Unit Hierarchy
//OU name BaseOU need to be created first
#define $Division ou##([ROOT])_division
#define $Unit ou##([ROOT])_unit
#define $Team ou##([ROOT])_team
#define $DivisionBranch ou=$Division,ou=BaseOU,[DOMAIN]
#define $UnitBranch ou=$Unit,ou=$Division,ou=BaseOU,[DOMAIN]
#define $TeamBranch ou=$Team,ou=$Unit,ou=$Division,ou=BaseOU,[DOMAIN]
#define $FQDN cn=$UserName,ou=$Team,ou=$Unit,ou=$Division,ou=BaseOU,[DOMAIN]
#define $BaseOU ou=BaseOU,[DOMAIN]
//OU name Groups under BaseOU need to be created first
#define $GroupOU ou=Groups,ou=BaseOU,[DOMAIN]
//----------------- TESTS ------------------------//
//-------------------- BINDS --------------------------//
Simple_Bind
{
TEST [BIND]
LOOP RAND
RANGE $DefaultRange
DN $FQDN
PWD T3stp$ss
}
Simple_Bind_2
{
TEST [BIND]
LOOP ONCE
RANGE $GroupRange
DN $FQDN
PWD T3stp$ss
}
//-------------------- UPDATES --------------------------//
Update_1Attr
{
TEST [MODIFY]
LOOP RAND
OP LDAP_MOD_REPLACE
RANGE $DefaultRange
DN $FQDN
ATTR homePhone:###(0-999)-###(0-999)-####(0-9999)
}
Update_10Attr
{
TEST [MODIFY]
LOOP RAND
OP LDAP_MOD_REPLACE
RANGE $DefaultRange
DN $FQDN
ATTR homePhone:###(0-999)-###(0-999)-####(0-9999)
ATTR pager:###(0-999)-###(0-999)-####(0-9999)
ATTR mobile:###(0-999)-###(0-999)-####(0-9999)
ATTR facsimileTelephoneNumber:###(0-999)-###(0-999)-####(0-9999)
ATTR ipPhone:###(0-999)-###(0-999)-####(0-9999)
ATTR company:TechnetWiki
ATTR title:Engineer
ATTR postOfficeBox:101010
ATTR streetAddress:1 Jane Doe Street
ATTR postalCode:101010
}
//-------------------- SEARCHES -----------------------//
Search_Base_1Attr
{
TEST [SEARCH]
LOOP RAND
RANGE $DefaultRange
DN $FQDN
FILTER (objectClass=*)
SCOPE LDAP_SCOPE_BASE
ATTR cn
}
Search_Base_10Attr
{
TEST [SEARCH]
LOOP RAND
RANGE $DefaultRange
DN $FQDN
FILTER (objectClass=*)
SCOPE LDAP_SCOPE_BASE
ATTR postalCode;postOfficeBox;streetAddress
ATTR homePhone;ipPhone;telephonenumber;title
}
Search_One_Level_1Attr
{
TEST [SEARCH]
LOOP RAND
RANGE $DefaultRange
DN $TeamBranch
FILTER (userPrincipalName=$UserName)
SCOPE LDAP_SCOPE_ONELEVEL
ATTR cn
}
Search_One_Level_10Attr
{
TEST [SEARCH]
LOOP RAND
RANGE $DefaultRange
DN $TeamBranch
FILTER (userPrincipalName=$UserName)
SCOPE LDAP_SCOPE_ONELEVEL
ATTR postalCode;postOfficeBox;streetAddress
ATTR homePhone;ipPhone;telephonenumber;title
}
Search_Subtree_1Attr
{
TEST [SEARCH]
LOOP RAND
RANGE $DefaultRange
DN $BaseOU
FILTER (userPrincipalName=$UserName)
SCOPE LDAP_SCOPE_SUBTREE
ATTR cn
}
Search_Subtree_10Attr
{
TEST [SEARCH]
LOOP RAND
RANGE $DefaultRange
DN $BaseOU
FILTER (userPrincipalName=$UserName)
SCOPE LDAP_SCOPE_SUBTREE
ATTR postalCode;postOfficeBox;streetAddress
ATTR homePhone;ipPhone;telephonenumber;title
}
Search_NonIndexed_1Attr
{
TEST [SEARCH]
LOOP RAND
RANGE $DefaultRange
DN $BaseOU
FILTER (department=WikiLDS-####(*))
SCOPE LDAP_SCOPE_SUBTREE
ATTR cn
}
Search_NonIndexed_10Attr
{
TEST [SEARCH]
LOOP RAND
RANGE $DefaultRange
DN $BaseOU
FILTER (department=wikiLDS-####(*))
SCOPE LDAP_SCOPE_SUBTREE
ATTR postalCode;postOfficeBox;streetAddress
ATTR homePhone;ipPhone;telephonenumber;title
}
//-------------------- SETUP --------------------------//
// Note: Order of these tests is not important but are processed more
// quickly at startup time if you define the inner tests first (e.g., AddDivision)
// and the outer tests second (e.g., NewRoot).
// Use NewRoot to run AddDivision, AddUnit and AddTeam all at once
AddDivision
{
TEST [ADD]
LOOP SEQ | ONCE
OP LDAP_MOD_ADD
DN $DivisionBranch
ATTR ObjectClass:organizationalUnit
ATTR name:$Division
ATTR instanceType:4
}
AddUnit
{
TEST [ADD]
LOOP SEQ | ONCE
OP LDAP_MOD_ADD
DN $UnitBranch
ATTR ObjectClass:organizationalUnit
ATTR name:$Unit
ATTR instanceType:4
}
AddTeam
{
TEST [ADD]
LOOP SEQ | ONCE
OP LDAP_MOD_ADD
DN $TeamBranch
ATTR ObjectClass:organizationalUnit
ATTR name:$Team
ATTR instanceType:4
}
// Typically run adtest -run newroot -root # where # is the root you want
NewRoot
{
RANGE #(1)
LOOP SEQ | ONCE
TEST AddDivision
TEST AddUnit
TEST AddTeam
}
AddUser
{
TEST [ADD]
LOOP SEQ | ONCE
OP LDAP_MOD_ADD
RANGE $DefaultRange
DN $FQDN
ATTR ObjectClass:user
ATTR cn:$UserName
ATTR userPrincipalName:$UserName
ATTR adminDescription:Uni
ATTR adminDisplayName:Uni
ATTR comment:Uni
ATTR company:Wiki
ATTR CountryCode:702
ATTR department:wikiLDS-$Padding(*)
ATTR description:Uni
ATTR displayName:$UserName
ATTR division:Uni
ATTR employeeID:Uni
ATTR facsimileTelephoneNumber:425-38383838
ATTR givenName:$UserName
ATTR homePhone:425-83838383
ATTR ipPhone:425-98989898
ATTR initials:Uni
ATTR mobile:425-89898989
ATTR otherHomePhone:425-10101010
ATTR otherIpPhone:Uni
ATTR otherMobile:425-12121212
ATTR otherPager:425-23232323
ATTR otherTelephone:425-67676767
ATTR pager:425-56565656
ATTR personalTitle:PM
ATTR physicalDeliveryOfficeName:Uni
ATTR postalAddress:Uni
ATTR postalCode:Uni
ATTR postOfficeBox:Uni
ATTR roomnumber:1326
ATTR streetAddress:Uni
ATTR telephonenumber:425-78787878
ATTR title:Engineer
ATTR userPassword:T3stp$ss
}
AddGroup
{
TEST [ADD]
LOOP SEQ|ONCE
OP LDAP_MOD_ADD
RANGE $GroupRange
DN cn=GrpAcc_$Padding(*),$GroupOU
ATTR ObjectClass:group
ATTR groupType:2147483650
ATTR name:GrpAcc_$Padding(*)
ATTR instanceType:4
}
//Add 50 users to a group
AddMembers
{
TEST [MODIFY]
LOOP SEQ|ONCE
OP LDAP_MOD_ADD
RANGE $GroupRange
DN cn=GrpAcc_$Padding([GROUP]),$GroupOU
ATTR member:$FQDN
}
//Add 2000 users to a group
AddMembers_2
{
TEST [MODIFY]
LOOP SEQ|ONCE
OP LDAP_MOD_ADD
RANGE $DefaultRange
DN cn=GrpAcc_$Padding([GROUP]),$GroupOU
ATTR member:$FQDN
}
---end test file---