1 j.alex 1.1.2.1 //%2006////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 j.alex 1.1.2.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
|
32 j.alex 1.1.2.2 // Author: Aruran (aruran.shanmug@in.ibm.com) & Melvin (msolomon@in.ibm.com),
33 // IBM for PEP# 241
|
34 j.alex 1.1.2.1 // Modified By:
35 //
36 //%/////////////////////////////////////////////////////////////////////////////
37
38 #include "TestStressTestClient.h"
39
40 PEGASUS_USING_PEGASUS;
41 PEGASUS_USING_STD;
42
|
43 j.alex 1.1.2.2 /** Constructor - Initializes the time variables and defines the Options
44 Table.
45 */
|
46 j.alex 1.1.2.1 TestStressTestClient::TestStressTestClient()
47 {
48 startMilliseconds = 0;
49 nowMilliseconds = 0;
50 nextCheckupInMillisecs = 0;
51 static struct OptionRow testOptionsTable[] = {
52 {"namespace", "", false, Option::STRING, 0, 0, "namespace",
|
53 j.alex 1.1.2.2 "specifies namespace to be used for the test"},
|
54 j.alex 1.1.2.1
55 {"classname", "", false, Option::STRING, 0, 0, "classname",
|
56 j.alex 1.1.2.2 "specifies classname to be used for the test"},
|
57 j.alex 1.1.2.1
58 {"verbose", "false", false, Option::BOOLEAN, 0, 0, "verbose",
59 "If set, outputs extra information "},
60
61 {"help", "false", false, Option::BOOLEAN, 0, 0, "help",
62 "Prints help message with command line options "},
63
64 {"ssl", "false", false, Option::BOOLEAN, 0, 0, "ssl", "use SSL"},
65
66 {"username", "", false, Option::STRING, 0, 0, "username",
|
67 j.alex 1.1.2.2 "Specifies user name"},
|
68 j.alex 1.1.2.1
69 {"password", "", false, Option::STRING, 0, 0, "password",
|
70 j.alex 1.1.2.2 "Specifies password"},
|
71 j.alex 1.1.2.1
72 {"port", "", false, Option::STRING, 0, 0, "port",
|
73 j.alex 1.1.2.2 "Port number on host"},
|
74 j.alex 1.1.2.1
75 {"clientid", "", true, Option::STRING, 0, 0, "clientid",
|
76 j.alex 1.1.2.2 "Client identification by controller"},
|
77 j.alex 1.1.2.1
78 {"pidfile", "", true, Option::STRING, 0, 0, "pidfile",
|
79 j.alex 1.1.2.2 "Client process log file"},
|
80 j.alex 1.1.2.1
81 {"clientlog", "", true, Option::STRING, 0, 0, "clientlog",
|
82 j.alex 1.1.2.2 "Client error log file"},
|
83 j.alex 1.1.2.1
84 {"hostname", "", false, Option::STRING, 0, 0, "hostname",
|
85 j.alex 1.1.2.2 "Host name"}
|
86 j.alex 1.1.2.1 };
87 optionCount = sizeof(testOptionsTable) / sizeof(testOptionsTable[0]);
88 optionsTable = testOptionsTable;
89 }
|
90 j.alex 1.1.2.2 /*///////////////////////////////////////////////////////////////
91 OPTION MANAGEMENT
92 ///////////////////////////////////////////////////////////////*/
|
93 j.alex 1.1.2.1
94 /** GetOptions function - This function sets up the options from
95 testOptionsTable which is initialized through constructor
96 using the option manager.
97 const char* optionName;
98 const char* defaultValue;
99 int required;
100 Option::Type type;
101 char** domain;
102 Uint32 domainSize;
103 const char* commandLineOptionName;
104 const char* optionHelpMessage;
105 */
106 int TestStressTestClient::GetOptions(
107 OptionManager& om,
108 int& argc,
109 char** argv,
110 OptionRow* newOptionsTable, Uint32 cOptionCount)
111 {
112 char **argvv;
113 int counter = 0;
114 j.alex 1.1.2.1 String argument = String::EMPTY;
|
115 j.alex 1.1.2.2
116 /** om.registerOptions(newOptionsTable, (const)cOptionCount); */
|
117 j.alex 1.1.2.1 om.registerOptions(newOptionsTable, cOptionCount);
118 argvv = argv;
119
|
120 j.alex 1.1.2.2 /** Following section is introduced to ignore options not
121 required by a client.
122 */
|
123 j.alex 1.1.2.1 for (int i = 1; i < argc; i++)
124 {
125 argument = String::EMPTY;
126 const char* arg = argv[i];
127
|
128 j.alex 1.1.2.2 /** Check for - option. */
|
129 j.alex 1.1.2.1 if (*arg == '-')
130 {
|
131 j.alex 1.1.2.2 /** Look for the option. */
|
132 j.alex 1.1.2.1 argument.append(arg + 1);
133 const Option* option = om.lookupOption(argument);
134
|
135 j.alex 1.1.2.2 /** Get the option argument if any. */
136 if (option)
|
137 j.alex 1.1.2.1 {
138 argvv[++counter]=argv[i];
139 if (option->getType() != Option::BOOLEAN)
140 {
|
141 j.alex 1.1.2.2 if (i + 1 != argc)
|
142 j.alex 1.1.2.1 {
|
143 j.alex 1.1.2.2 argvv[++counter] = argv[++i];
|
144 j.alex 1.1.2.1 }
145 }
146 }
147 }
|
148 j.alex 1.1.2.2 }
149 ++counter;
|
150 j.alex 1.1.2.1 om.mergeCommandLine(counter, argvv);
151 om.checkRequiredOptions();
152 return counter;
153 }
154
|
155 j.alex 1.1.2.2 /** This method is used by clients to register client specific required
156 options to the option table. All these options are taken as mandatory one.
|
157 j.alex 1.1.2.1 */
158 OptionRow *TestStressTestClient::generateClientOptions(
159 OptionRow* clientOptionsTable,
160 Uint32 clientOptionCount,
161 Uint32& totalOptions)
162 {
163
164 Uint32 currOptionCount = 0;
165 static struct OptionRow *newOptionsTable = 0;
166
167 totalOptions = optionCount + clientOptionCount;
168
169 newOptionsTable = new struct OptionRow[totalOptions];
170
|
171 j.alex 1.1.2.2 for (; currOptionCount < optionCount; currOptionCount++)
|
172 j.alex 1.1.2.1 {
173 newOptionsTable[currOptionCount] = optionsTable[currOptionCount];
174 }
175 for (Uint32 i =0; i < clientOptionCount; i++)
176 {
177 newOptionsTable[currOptionCount] = clientOptionsTable[i];
178 currOptionCount++;
179 }
180 return newOptionsTable;
181 }
182
|
183 j.alex 1.1.2.2 /** This method is used by the clients to log information which are required
184 for controller reference. It logs the information with Client ID and
185 status of the client in the PID File log file.
|
186 j.alex 1.1.2.1 */
|
187 j.alex 1.1.2.2 void TestStressTestClient::logInfo(
188 String clientId,
189 pid_t clientPid,
190 int clientStatus,
191 String &pidFile)
|
192 j.alex 1.1.2.1 {
|
193 j.alex 1.1.2.2 String line, searchString, subLine;
194 int indx = 0;
|
195 j.alex 1.1.2.1 char pid_str[15];
196 char status_str[15];
197 char time_str[32];
198
|
199 j.alex 1.1.2.2 searchString.append(clientId.getCString());
|
200 j.alex 1.1.2.1
|
201 j.alex 1.1.2.2 #ifdef PEGASUS_OS_TYPE_WINDOWS
202 int offset = 2;
203 #else
|
204 j.alex 1.1.2.1 int offset = 1;
205 #endif
206
|
207 j.alex 1.1.2.2 Uint32 whileCount = 0;
208
209 /** Get current time for time stamp */
|
210 j.alex 1.1.2.1 nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
211
212 sprintf(pid_str, "%d", clientPid);
213 sprintf(status_str, "%d", clientStatus);
|
214 j.alex 1.1.2.2 sprintf(time_str, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u",
215 nowMilliseconds);
216
217 fstream pFile(pidFile.getCString(),ios::in|ios::out);
|
218 j.alex 1.1.2.1
219 Boolean addClient= false;
220
|
221 j.alex 1.1.2.2 #ifdef PEGASUS_OS_TYPE_WINDOWS
222 if (pFile.is_open())
|
223 j.alex 1.1.2.1 #else
|
224 j.alex 1.1.2.2 if (pFile)
|
225 j.alex 1.1.2.1 #endif
226 {
|
227 j.alex 1.1.2.2 while(!pFile.eof())
228 {
229 whileCount++;
230 GetLine (pFile,line);
|
231 j.alex 1.1.2.1 indx=line.find(':');
|
232 j.alex 1.1.2.2 if (indx > 0)
|
233 j.alex 1.1.2.1 {
|
234 j.alex 1.1.2.2 subLine.append(line.subString(0, indx));
|
235 j.alex 1.1.2.1 }
|
236 j.alex 1.1.2.2 if (String::compare(subLine, searchString) == 0)
|
237 j.alex 1.1.2.1 {
238 long pos;
239 addClient = true;
|
240 j.alex 1.1.2.2 pos = pFile.tellp();
241 pFile.seekp(pos - line.size()-offset);
242 String newLine = String(clientId.getCString());
243 newLine.append("::");
244 newLine.append(pid_str);
245 newLine.append("::");
246 newLine.append(status_str);
247 newLine.append("::");
248 newLine.append(time_str);
249 if (line.size() > newLine.size())
|
250 j.alex 1.1.2.1 {
|
251 j.alex 1.1.2.2 Uint32 jSize = line.size() - newLine.size();
252 pFile.write(newLine.getCString(),newLine.size());
253 for (Uint32 i =0;i<jSize;i++)
254 {
255 pFile.write(" ",1);
256 }
|
257 j.alex 1.1.2.1 }
258 else
259 {
|
260 j.alex 1.1.2.2 pFile.write(newLine.getCString(),newLine.size());
|
261 j.alex 1.1.2.1 }
262 break;
|
263 j.alex 1.1.2.2 }
264 subLine.clear();
|
265 j.alex 1.1.2.1 line.clear();
266 }
267 if(!addClient)
268 {
|
269 j.alex 1.1.2.2 pFile.close();
270 fstream pFile(pidFile.getCString(),ios::out|ios::app);
271 pFile<<clientId<<"::"<<clientPid<<"::"<<clientStatus<<"::"
272 <<time_str<<"\n";
|
273 j.alex 1.1.2.1 }
274 }
|
275 j.alex 1.1.2.2 pFile.close();
|
276 j.alex 1.1.2.1 }
277
278 /** This method is used to take the client process start time.*/
279 void TestStressTestClient::startTime()
280 {
281 startMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
282 nowMilliseconds = startMilliseconds;
283 }
284
|
285 j.alex 1.1.2.2 /** This method is used to check the time stamp for logging information about
286 the success or failure.
|
287 j.alex 1.1.2.1 */
288 Boolean TestStressTestClient::checkTime()
289 {
290 nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
291
|
292 j.alex 1.1.2.2 if (nowMilliseconds >= nextCheckupInMillisecs)
|
293 j.alex 1.1.2.1 {
|
294 j.alex 1.1.2.2 nextCheckupInMillisecs = (Uint64)convertmin2millisecs(CHECKUP_INTERVAL)
295 + nowMilliseconds;
|
296 j.alex 1.1.2.1 return true;
297 }
298 return false;
299 }
300
|
301 j.alex 1.1.2.2 /** This method is used to log the information about the client's success or
302 failure percentage at a specific interval of time.
|
303 j.alex 1.1.2.1 */
|
304 j.alex 1.1.2.2 void TestStressTestClient::logErrorPercentage(
305 Uint32 successCount,
306 Uint32 totalCount,
307 pid_t clientPid,
308 String &clientLog,
309 char client[])
|
310 j.alex 1.1.2.1 {
311 Uint32 successPercentage, errorPercentage;
312 successPercentage = (successCount/totalCount)*100;
313 errorPercentage = 100 - successPercentage;
|
314 j.alex 1.1.2.2
315 /** loging details here */
316 ofstream errorLog_File(clientLog.getCString(), ios::app);
317 errorLog_File<<client<<" PID#"<<clientPid<<" ran "<<totalCount
318 <<" times with a "<<errorPercentage<<"% failure"<<"\n";
319 errorLog_File.close();
|
320 j.alex 1.1.2.1 }
321
|
322 j.alex 1.1.2.2 /** This method is used to log the informations of client logs to the client
323 log file.
324 */
325 void TestStressTestClient::errorLog(
326 pid_t clientPid,
327 String &clientLog,
328 String &message)
|
329 j.alex 1.1.2.1 {
|
330 j.alex 1.1.2.2 /** loging details here .*/
331 ofstream errorLog_File(clientLog.getCString(), ios::app);
332 errorLog_File<<" PID#"<<clientPid<<"::"<<message<<"\n";
333 errorLog_File.close();
|
334 j.alex 1.1.2.1 }
335
336 /** This method handles the SSLCertificate verification part. */
|
337 j.alex 1.1.2.2 static Boolean verifyCertificate(SSLCertificateInfo &certInfo)
|
338 j.alex 1.1.2.1 {
|
339 j.alex 1.1.2.2 /** Add code to handle server certificate verification. */
|
340 j.alex 1.1.2.1 return true;
341 }
342
|
343 j.alex 1.1.2.2 /** This method is used by the clients to connect to the server. If useSSL is
344 true then an SSL connection will be atemped with the userName and passWord
345 that is passed in. Otherwise connection will be established using
346 localhost. All parameters are required.
|
347 j.alex 1.1.2.1 */
348 void TestStressTestClient::connectClient(
349 CIMClient *client,
350 String host,
351 Uint32 portNumber,
352 String userName,
353 String password,
354 Boolean useSSL,
355 Uint32 timeout,
356 Boolean verboseTest)
357 {
358 if (useSSL)
359 {
|
360 j.alex 1.1.2.2 /** Get environment variables. */
361 const char* pegasusHome = getenv("PEGASUS_HOME");
362
363 String trustpath = FileSystem::getAbsolutePath(
364 pegasusHome, PEGASUS_SSLCLIENT_CERTIFICATEFILE);
|
365 j.alex 1.1.2.1
|
366 j.alex 1.1.2.2 String randFile = String::EMPTY;
|
367 j.alex 1.1.2.1
368 #ifdef PEGASUS_SSL_RANDOMFILE
|
369 j.alex 1.1.2.2 randFile = FileSystem::getAbsolutePath(
370 pegasusHome,
371 PEGASUS_SSLCLIENT_RANDOMFILE);
|
372 j.alex 1.1.2.1 #endif
|
373 j.alex 1.1.2.2
374 SSLContext sslContext(
375 trustpath, verifyCertificate, randFile);
376 if (verboseTest)
377 {
378 PEGASUS_STD(cout) << "connecting to " << host << ":"
379 << portNumber << " using SSL"
380 << PEGASUS_STD(endl);
381 }
382 client->connect (host, portNumber, sslContext, userName, password);
383 } /* useSSL. */
|
384 j.alex 1.1.2.1 else
385 {
|
386 j.alex 1.1.2.2 if (verboseTest)
387 {
388 PEGASUS_STD(cout) << "Connecting to " << host << ":" << portNumber
389 << PEGASUS_STD(endl);
390 }
391 client->connect (host, portNumber, userName, password);
|
392 j.alex 1.1.2.1 }
393 if (verboseTest)
394 {
|
395 j.alex 1.1.2.2 PEGASUS_STD(cout) << "Client Connected" << PEGASUS_STD(endl);
|
396 j.alex 1.1.2.1 }
397 }
|