Load Testing a NetWare 5.1 Server
Articles and Tips: article
Sr. Program Systems Analyst
Rush Presbyterian St. Luke's Medical Center
sulinski@rush.edu
01 Oct 2002
We needed to run a load test on a NetWare 5.1 server, simulating a large number of users connected to the server. The requirements set by the engineers were to have as many users logged in as possible, using files and leaving them open. There also needed to be at least 30% utilization, good traffic, and use of the dirty cache buffers.
After researching several Load Testing software packages, we discovered that there was no software package available to provide us with the type of load testing we desired. Because of this, we began to look into alternative options in order to perform a reasonable load test of the server.
Since we were new to NetWare programming, the discovery of NetBasic was an epiphany to the project. After looking at the documentation, we concluded that it would be possible to write a script in NetBasic that would simulate as many users as needed. The final code allowed us to simulate 1,000 users logged in, and we were able to actually provide a heavier load than what is currently on our production systems.
The NetBasic program we wrote consisted of two parts. The first part was a loader program that created users and spawned a second program. Once the second program was spawned, it would simulate the users logging into the tree, processing files, and generating network traffic. Here is the code for our first NetBasic program.
SRVLOAD.BAS To Run: SRVLOAD <#of USERS> <#of Days to Run> Sub Main ' Number of user to create RunCount = Data:INTEGER (SYS:Param(2)) ' Number of Hours to run each spawned user RunTime = Data:String (SYS:Param(3)) ' Login as an admin NDS:Session:Login("admin", "pasword"); ' Change this line for your Tree ' Change CX to CX for user creation NDS:CONTEXT:PATH:CHANGE("Users.rpslmc"); ' Change this line for your Tree ' Sets X to 0 x=0 ' Do creates user and spawns additional programs to run as user Do While (true) ' Exits the program on demand by creating an END.NOW ' file in the directory EHandle = FIO:OPEN("Vol1:\File\END.NOW", "r") If (ERR = 0); Quit; EndIf ' sets the amount of users to create, once the amount ' is reached the program quits If (x = RunCount) Out = NDS:Session:Logout; Exit; EndIf ' Generates a random number for user creation ' Random number creates minor security since ' no password will associated with user UserN = Data:String(Math:Random * 10) ' Creates the user ID Success=NDS:ADD:User(UserN,UserN) If (Success) x = x + 1 ' Copies the NetBasic Program runuser.bas to random(USER) number ' And runs the program as the user. If Dir:File:Copy ("SYS:\Program\runuser.bas","SYS:\Program\Users\" + UserN +".bas") RunP = "SYS:\Program\Users\" + UserN + ".bas" Spawn = SYS:Call ("Run.nlm "+ RunP + " " + UserN + " " + RunTime + " " + Data:String(x)); Else Quit: EndIf EndIf EndDo End Sub &_;&_;&_;&_;&_;&_;&_;&_;&_;&_;&_;___
The second program goes as follows:
RUNUSER.BAS Runuser.bas is auto loaded by the srvload.bas. Sub Main ' Sets user name passed from SRVLOAD.BAS CUser= Data:String (SYS:Param(2)) ' Sets the length of days the program is to run passed from SRVLOAD.BAS LTime= Data:Integer (SYS:Param(3)) ' Sets the current spawned number passed from SRVLOAD.BAS Spawn = Data:String (SYS:Param(4)) ' Sets fOpen counter Count = 0 ' Sets FTPCount counter for naming FTP'd file FTPCount = 0 ' Login as user NDS:Session:Login (".CN=" + cuser + ".OU=USERS.O=RPSLMC", ""); 'Change this for your TREE ' Sets the length of time to run in days SecondsInWeek = ltime*24*60*60 ServerDateObj = NET:Server:Date:Get Date = ServerDateObj.Date Time = ServerDateObj.Time NextWeek = DATE:UTF (Date, Time) + SecondsInWeek DateObj = DATE:Object(NextWeek) ' Changes Dir to VOL1:\Files makes new Dir as User and switches to it, 'If fails, Quits app If (Dir:Change ("VOL1:\File")) Dir:Make (cuser) Dir:Change (Cuser) UserDir = DIR:Current Else Quit EndIf x=0 ' Runs until the amount of time passes that is passed from the command line Do While (True) ' Checks time and compares to start time. ' If suffcient time passes exits the loop ServerDateObj2 = NET:Server:Date:Get ' Looks for a file called END.NOW in the VOL1:File dir. ' If the file exsists program exits the loop EHandle = FIO:OPEN("Vol1:\File\END.NOW", "r") If ((ServerDateObj2.date >= DateObj.date) & (ServerDateObj2.Time >= DateObj.Time)|(ERR = 0)); ' Closes any open files Count = Count - 1 Do While (True) If (Count <= 0) Quit EndIf FIO:Close(fOpen(Count)) Count = Count - 1 EndDo Out = NDS:Session:Logout Quit; EndIf ' Random generatated number to run new process as the user DoIt = 0 DoIt = ((Math:Random * 10 ) / 32767) ' Writes user's current status on screen WIN:AT (1,1); WIN:SAY ("Current User: " + CUser + " Spawn Number:" + Spawn); ' Makes Files ' Will open the total amount you specify, will allow for 26 ' files for each user. If (((DoIt = 4) | (DoIt = 5) | (DoIt = 6) | (DoIt = 7) | (DoIt = 8)) & (Count <= 26)) WIN:AT (2,1); WIN:SAY ("Opening File " + Data:String(DoIT) + " " + Data:String(ServerDateObj2.Time) + " " + Data:String(Count) +" ") Mode = "w+"+"t" Handle = FIO:Open (Data:String(Math:Random * 10) + ".tst", Mode) If (ERR = 0) fOpen(Count) = Handle FIO:Write (Handle, "TestString1", "TestString2") Count = Count + 1 EndIf EndIf
' Close File If (((DoIt = 2) | (DoIt = 3)) & (Count > 0)) WIN:AT (2,1); WIN:SAY ("Closing File " + Data:String(DoIT) + " " + Data:String(ServerDateObj2.Time) + " ") If (Count > 0) cCount = Count - 1 If (FIO:Close (fOpen(cCount))) Count = Count - 1 WIN:AT (2,1); WIN:SAY ("Closing File " + Data:String(DoIT) + " " + Data:String(ServerDateObj2.Time) + " Success") EndIf EndIf EndIf ' Copy a file If (DoIt = 1) WIN:AT (2,1); WIN:SAY ("Copy File " + Data:String(DoIT) + " " + Data:String(ServerDateObj2.Time)) DIR:FILE:COPY ("sys:\Program\copy.pdf", UserDir + "\" + Data:String(FTPCount) + Cuser + ".pdf") EndIf ' Deletes Files If (DoIt = 0) WIN:AT (2,1); WIN:SAY ("Deleting File " + Data:String(DoIT) + " " + Data:String(ServerDateObj2.Time) + " ") fobj = Dir:First ("*.*", 0 ) fCount = 1 Do while (fobj.error = 0) fCount = fCount + 1 fobj = Dir:Next (fobj) EndDo CFile = 1 fobj = Dir:First ("*.*", 0 ) KFile = ((Math:Random * fcount) /32767 ) Do While (CFile < fCount) If (kFile = cFile) Dir:File:Delete (fobj.name + "." + fobj.extension) EndIf fobj = Dir:Next (fobj) CFile = CFile + 1 EndDo EndIf FTPCount = FTPCount + 1 ' Generates light traffic FTP:Verbose (0) FTP:Login ("ftp.Novell.Com","anonymous", "me@email.com"); ' Above line needs to be modified FTP:CD ("pub"); 'You may need to modify this line FTP:Logout WIN:AT (3,1); WIN:SAY ("Open File Count :" + Data:String(Count) + " ")
EndDo End sub
Note: When we used this program to run our simulations, we needed to modify several set commands in order to keep the system from crashing, such as:
Note: Set Maximum File Locks = 75000 Set Minimum Directory Cache Buffers = 2000 Set Maximum Directory Cache Buffers = 4000 Set Maximum Concurrent Directory Cache Writes = 500
Conclusion
It is critical to take into account that each simulated user is running an instance of RUN.NLM. Because of the amount of activity generated on the server during the debugging and testing of these programs, we often crashed the server while performing things like using the Remote Console. The FILESYS.NLM constantly ran out of memory and certain screens in Monitor also crashed the server. We determined that these crashes were not due to faults in our two programs, however. The programs are solid; you just need to experiment with the number of users and open files for your particular test system to achieve a workable test environment.
* Originally published in Novell AppNotes
Disclaimer
The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.