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