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