1 j.alex 1.2 //%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.2 // 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 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include "TestStressTestClient.h"
35
36 PEGASUS_USING_PEGASUS;
37 PEGASUS_USING_STD;
38
39 /** Constructor - Initializes the time variables and defines the Options
40 Table.
41 */
42 TestStressTestClient::TestStressTestClient()
43 j.alex 1.2 {
44 startMilliseconds = 0;
45 nowMilliseconds = 0;
46 nextCheckupInMillisecs = 0;
47 static struct OptionRow testOptionsTable[] = {
48 {"namespace", "", false, Option::STRING, 0, 0, "namespace",
49 "specifies namespace to be used for the test"},
50
51 {"classname", "", false, Option::STRING, 0, 0, "classname",
52 "specifies classname to be used for the test"},
53
54 {"verbose", "false", false, Option::BOOLEAN, 0, 0, "verbose",
55 "If set, outputs extra information "},
56
57 {"help", "false", false, Option::BOOLEAN, 0, 0, "help",
58 "Prints help message with command line options "},
59
|
60 thilo.boehm 1.5 #ifdef PEGASUS_HAS_SSL
|
61 j.alex 1.2 {"ssl", "false", false, Option::BOOLEAN, 0, 0, "ssl", "use SSL"},
|
62 thilo.boehm 1.5 #endif
|
63 j.alex 1.2
64 {"username", "", false, Option::STRING, 0, 0, "username",
65 "Specifies user name"},
66
67 {"password", "", false, Option::STRING, 0, 0, "password",
68 "Specifies password"},
69
70 {"port", "", false, Option::STRING, 0, 0, "port",
71 "Port number on host"},
72
73 {"clientid", "", true, Option::STRING, 0, 0, "clientid",
74 "Client identification by controller"},
75
76 {"pidfile", "", true, Option::STRING, 0, 0, "pidfile",
77 "Client process log file"},
78
79 {"clientlog", "", true, Option::STRING, 0, 0, "clientlog",
80 "Client error log file"},
81
82 {"hostname", "", false, Option::STRING, 0, 0, "hostname",
83 "Host name"}
84 j.alex 1.2 };
85 optionCount = sizeof(testOptionsTable) / sizeof(testOptionsTable[0]);
86 optionsTable = testOptionsTable;
87 }
88 /**
89 OPTION MANAGEMENT
90 */
91
92 /** GetOptions function - This function sets up the options from
93 testOptionsTable which is initialized through constructor
94 using the option manager.
95 const char* optionName;
96 const char* defaultValue;
97 int required;
98 Option::Type type;
99 char** domain;
100 Uint32 domainSize;
101 const char* commandLineOptionName;
102 const char* optionHelpMessage;
103 */
104 int TestStressTestClient::GetOptions(
105 j.alex 1.2 OptionManager& om,
106 int& argc,
107 char** argv,
108 OptionRow* newOptionsTable, Uint32 cOptionCount)
109 {
110 char **argvv;
111 int counter = 0;
112 String argument = String::EMPTY;
113
114
115 //
116 // om.registerOptions(newOptionsTable, (const)cOptionCount);
117 //
118 om.registerOptions(newOptionsTable, cOptionCount);
119 argvv = argv;
120
121 //
122 // Following section is introduced to ignore options not
123 // required by a client.
124 //
125 for (int i = 1; i < argc; i++)
126 j.alex 1.2 {
127 argument = String::EMPTY;
128 const char* arg = argv[i];
129
130 //
131 // Check for - option.
132 //
133 if (*arg == '-')
134 {
135 //
136 // Look for the option.
137 //
138 argument.append(arg + 1);
139 const Option* option = om.lookupOption(argument);
140
141 //
142 // Get the option argument if any.
143 //
144 if (option)
145 {
146 argvv[++counter]=argv[i];
147 j.alex 1.2 if (option->getType() != Option::BOOLEAN)
148 {
149 if (i + 1 != argc)
150 {
151 argvv[++counter] = argv[++i];
152 }
153 }
154 }
155 }
156 }
157 ++counter;
158 om.mergeCommandLine(counter, argvv);
159 om.checkRequiredOptions();
160 return counter;
161 }
162
163 /** This method is used by clients to register client specific required
164 options to the option table. All these options are taken as mandatory one.
165 */
166 OptionRow *TestStressTestClient::generateClientOptions(
167 OptionRow* clientOptionsTable,
168 j.alex 1.2 Uint32 clientOptionCount,
169 Uint32& totalOptions)
170 {
171
172 Uint32 currOptionCount = 0;
173 static struct OptionRow *newOptionsTable = 0;
174
175 totalOptions = optionCount + clientOptionCount;
176
177 newOptionsTable = new struct OptionRow[totalOptions];
178
179 for (; currOptionCount < optionCount; currOptionCount++)
180 {
181 newOptionsTable[currOptionCount] = optionsTable[currOptionCount];
182 }
183 for (Uint32 i =0; i < clientOptionCount; i++)
184 {
185 newOptionsTable[currOptionCount] = clientOptionsTable[i];
186 currOptionCount++;
187 }
188 return newOptionsTable;
189 j.alex 1.2 }
190
191 /** This method is used by the clients to log information which are required
192 for controller reference. It logs the information with Client ID and
193 status of the client in the PID File log file.
194 */
195 void TestStressTestClient::logInfo(
196 String clientId,
197 pid_t clientPid,
198 int clientStatus,
199 String &pidFile)
200 {
201 char pid_str[15];
202 char status_str[15];
203 char time_str[32];
204
205 #ifdef PEGASUS_OS_TYPE_WINDOWS
206 int offset = 2;
207 #else
208 int offset = 1;
209 #endif
210 j.alex 1.2
211 //
212 // Get current time for time stamp
213 //
214 nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
215
216 sprintf(pid_str, "%d", clientPid);
217 sprintf(status_str, "%d", clientStatus);
218 sprintf(time_str, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u",
219 nowMilliseconds);
220
221 fstream pFile(pidFile.getCString(),ios::in|ios::out);
222
223 Boolean addClient= false;
224
|
225 kumpf 1.4 if (!!pFile)
|
226 j.alex 1.2 {
|
227 kumpf 1.4 String line;
228 while(!pFile.eof() && GetLine(pFile, line))
|
229 j.alex 1.2 {
|
230 kumpf 1.4 String subLine;
231
232 Uint32 indx=line.find(':');
233 if (indx != PEG_NOT_FOUND)
|
234 j.alex 1.2 {
|
235 kumpf 1.4 subLine = line.subString(0, indx);
|
236 j.alex 1.2 }
|
237 kumpf 1.4
238 if (String::compare(subLine, clientId) == 0)
|
239 j.alex 1.2 {
240 long pos;
241 addClient = true;
|
242 a.dunfey 1.3 pos = (long)pFile.tellp();
|
243 j.alex 1.2 pFile.seekp(pos - line.size()-offset);
|
244 kumpf 1.4 String newLine = clientId;
|
245 j.alex 1.2 newLine.append("::");
246 newLine.append(pid_str);
247 newLine.append("::");
248 newLine.append(status_str);
249 newLine.append("::");
250 newLine.append(time_str);
|
251 kumpf 1.4
252 Sint32 jSize = line.size() - newLine.size();
253 CString newLineCString = newLine.getCString();
254 pFile.write(newLineCString, strlen(newLineCString));
255 for (Sint32 i = 0; i < jSize; i++)
|
256 j.alex 1.2 {
|
257 kumpf 1.4 pFile.write(" ",1);
|
258 j.alex 1.2 }
259 break;
260 }
261 }
262 if(!addClient)
263 {
264 pFile.close();
265 fstream pFile(pidFile.getCString(),ios::out|ios::app);
266 pFile<<clientId<<"::"<<clientPid<<"::"<<clientStatus<<"::"
267 <<time_str<<"\n";
268 }
269 }
270 pFile.close();
271 }
272
273 /** This method is used to take the client process start time.*/
274 void TestStressTestClient::startTime()
275 {
276 startMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
277 nowMilliseconds = startMilliseconds;
278 }
279 j.alex 1.2
280 /** This method is used to check the time stamp for logging information about
281 the success or failure.
282 */
283 Boolean TestStressTestClient::checkTime()
284 {
285 nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
286
287 if (nowMilliseconds >= nextCheckupInMillisecs)
288 {
289 nextCheckupInMillisecs = (Uint64)convertmin2millisecs(CHECKUP_INTERVAL)
290 + nowMilliseconds;
291 return true;
292 }
293 return false;
294 }
295
296 /** This method is used to log the information about the client's success or
297 failure percentage at a specific interval of time.
298 */
299 void TestStressTestClient::logErrorPercentage(
300 j.alex 1.2 Uint32 successCount,
301 Uint32 totalCount,
302 pid_t clientPid,
303 String &clientLog,
304 char client[])
305 {
306 Uint32 successPercentage, errorPercentage;
307 successPercentage = (successCount/totalCount)*100;
308 errorPercentage = 100 - successPercentage;
309
310 //
311 // loging details here
312 //
313 ofstream errorLog_File(clientLog.getCString(), ios::app);
314 errorLog_File<<client<<" PID#"<<clientPid<<" ran "<<totalCount
315 <<" times with a "<<errorPercentage<<"% failure"<<"\n";
316 errorLog_File.close();
317 }
318
319 /** This method is used to log the informations of client logs to the client
320 log file.
321 j.alex 1.2 */
322 void TestStressTestClient::errorLog(
323 pid_t clientPid,
324 String &clientLog,
325 String &message)
326 {
327 //
328 // loging details here .
329 //
330 ofstream errorLog_File(clientLog.getCString(), ios::app);
331 errorLog_File<<" PID#"<<clientPid<<"::"<<message<<"\n";
332 errorLog_File.close();
333 }
334
335 /** This method handles the SSLCertificate verification part. */
336 static Boolean verifyCertificate(SSLCertificateInfo &certInfo)
337 {
338 //
339 // Add code to handle server certificate verification.
340 //
341 return true;
342 j.alex 1.2 }
343
344 /** This method is used by the clients to connect to the server. If useSSL is
345 true then an SSL connection will be atemped with the userName and passWord
346 that is passed in. Otherwise connection will be established using
347 localhost. All parameters are required.
348 */
349 void TestStressTestClient::connectClient(
350 CIMClient *client,
351 String host,
352 Uint32 portNumber,
353 String userName,
354 String password,
355 Boolean useSSL,
356 Uint32 timeout,
357 Boolean verboseTest)
358 {
359 if (useSSL)
360 {
|
361 thilo.boehm 1.5 #ifdef PEGASUS_HAS_SSL
|
362 j.alex 1.2 //
363 // Get environment variables.
364 //
365 const char* pegasusHome = getenv("PEGASUS_HOME");
366
367 String trustpath = FileSystem::getAbsolutePath(
368 pegasusHome, PEGASUS_SSLCLIENT_CERTIFICATEFILE);
369
370 String randFile = String::EMPTY;
371
372 #ifdef PEGASUS_SSL_RANDOMFILE
373 randFile = FileSystem::getAbsolutePath(
374 pegasusHome,
375 PEGASUS_SSLCLIENT_RANDOMFILE);
376 #endif
377
378 SSLContext sslContext(
379 trustpath, verifyCertificate, randFile);
380 if (verboseTest)
381 {
382 cout << "connecting to " << host << ":"
383 j.alex 1.2 << portNumber << " using SSL"
384 << endl;
385 }
386 client->connect (host, portNumber, sslContext, userName, password);
|
387 thilo.boehm 1.5 #else
388 PEGASUS_ASSERT(false);
389 #endif
|
390 j.alex 1.2 } /* useSSL. */
391 else
392 {
393 if (verboseTest)
394 {
395 cout << "Connecting to " << host << ":" << portNumber
396 << endl;
397 }
398 client->connect (host, portNumber, userName, password);
399 }
400 if (verboseTest)
401 {
402 cout << "Client Connected" << endl;
403 }
404 }
|