BUG#: 8730
[tpot/pegasus/.git] / src / Clients / cimcli / CIMCLICommand.cpp
1 //%LICENSE////////////////////////////////////////////////////////////////
2 //
3 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //////////////////////////////////////////////////////////////////////////
29 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 /*
33     This module contains main() for cimcli.
34     It executes the setup,
35                 input parameter analysis
36                     directly for the object definition (second parameter)
37                     other parameters through CIMCLIOptions
38                  connect
39                 calling the proper action function per the input operation
40                     parameter
41                 operation repeats
42                 close of the connect
43                 output of summary information
44                 output of timing information
45     Legal operation are defined in CIMCLIOperations.  Legal input parameters
46     are defined in CIMCLIOptions.
47 */
48 #include <Pegasus/Common/Config.h>
49 #include <Pegasus/Common/PegasusAssert.h>
50 #include <Pegasus/Common/Constants.h>
51 #include <Pegasus/Common/Threads.h>
52 #include <Pegasus/Common/Tracer.h>
53 #include <Pegasus/Common/HostLocator.h>
54
55 #include <Pegasus/Client/CIMClient.h>
56 #include <Pegasus/General/Stopwatch.h>
57
58 #include <Clients/cimcli/CIMCLIClient.h>
59 #include <Clients/cimcli/CIMCLIHelp.h>
60 #include <Clients/cimcli/CIMCLIOptions.h>
61 #include <Clients/cimcli/CIMCLIOperations.h>
62
63 #ifdef PEGASUS_OS_ZOS
64 #include <Pegasus/General/SetFileDescriptorToEBCDICEncoding.h>
65 #endif
66
67 PEGASUS_USING_PEGASUS;
68 PEGASUS_USING_STD;
69
70 /////////////////////////////////////////////////////////////////////////
71 //
72 // The following functions process the target object parameter for
73 // particular action functions.
74 //
75 //////////////////////////////////////////////////////////////////////////
76
77 /** getClassNameInput - gets the classname object
78  * and puts in into the opts.className holder
79  * If rqd, parameter must exist and error generated if it does
80  * not exist. Otherwise it subsitutes NULL for the string. Also
81  * puts the arguement in inputObjectName for possible error
82  * display
83  * @param argc number of input arguments. Used to determine if
84  *             required argument exits
85  * @param argv List of input arguments. Argument for conversion
86  *             to classname is in this list.
87  * @param opts Options Structure reference. Puts results into
88  *             this structure
89  * @param- rqd - true if parameter required
90  * @return True if parameter found. False if parameter not
91  *         required and required.
92 */
93 Boolean _getClassNameInput(int argc, char** argv, Options& opts, Boolean rqd)
94 {
95     if (argc > 2)
96     {
97         opts.inputObjectName = argv[2];
98         try
99         {
100             opts.className = CIMName(argv[2]);
101         }
102
103         catch(Exception& e)
104         {
105             cerr << "Error: Input class name invalid."
106                  << endl << e.getMessage() << endl
107                  << "Must be the class Name as defined by DMTF Spec."
108                  << " Input Probably contains invalid character. "
109                  << endl;
110             exit(CIMCLI_RTN_CODE_PEGASUS_EXCEPTION);
111         }
112     }
113     else // Parameter does not exist
114     {
115         opts.inputObjectName = "";
116         if (rqd)
117         {
118                 cerr << "Error: Class Name Required. ex. gc CIM_Door" << endl;
119                 return(false);
120         }
121         else   // set the opts properties to indicate no classname input
122         {
123                 opts.className = CIMName();
124         }
125     }
126     return(true);
127 }
128 /** getObjectName - gets the objectname object
129  * and puts in into the opts.className holder
130  * If rqd, parameter must exist. Otherwise
131  * it subsitutes NULL for the string.
132  * Also puts the argument in inputObjectName for possible error
133  * display
134  * @param argc number of input arguments. Used to determine if
135  *             required argument exits
136  * @param argv List of input arguments. Argument for conversion
137  *             to classname is in this list.
138  * @param opts Options Structure reference. Puts results into
139  *             this structure
140  * @param- rqd - true if parameter required
141  * @return True if parameter found.
142 */
143 Boolean _getObjectNameInput(int argc, char** argv, Options& opts, Boolean rqd)
144 {
145     if (argc > 2)
146     {
147         opts.inputObjectName = argv[2];  // save for possible eror report
148         try
149         {
150             opts.targetObjectName = argv[2];
151         }
152         catch(Exception& e)
153         {
154             cerr << "Error: Input ObjectPath formatted incorrectly."
155                  << endl << e.getMessage() << endl
156                  << "Must be model path defined by DMTF Spec."
157                  << endl;
158             exit(CIMCLI_RTN_CODE_PEGASUS_EXCEPTION);
159         }
160     }
161     else
162     {
163         opts.inputObjectName = "";
164         if (rqd)
165         {
166                 cerr << "Error: Object Name Required" << endl;
167                 return(false);
168         }
169         else
170         {
171                 opts.targetObjectName = CIMObjectPath();
172         }
173     }
174     return(true);
175 }
176
177 /** _getQualifierNameInput - Gets a single parameter for
178  * qualifier. Puts input into inputObjectName for possible error
179  * display
180  * @return true if parameter found
181 */
182 Boolean _getQualifierNameInput(int argc, char** argv, Options& opts)
183 {
184     if (argc > 2)
185     {
186         opts.qualifierName = argv[2];
187         opts.inputObjectName = argv[2];
188     }
189     else
190     {
191         cerr << "Qualifier Name Required" << endl;
192         return(false);
193     }
194     return(true);
195 }
196
197 /*
198     Function to handle Client Operation Performance data if the
199     server returns this data.
200     FUTURE - This code still caries some of the tests that were
201     initally implemented when the callback was first created.  We should
202     explore removing or modifying these tests. At least partly fixed by
203     making the displays conditional on verboseTest
204 */
205 bool _localVerboseTest;
206 ClientOpPerformanceData returnedPerformanceData;
207 class ClientStatistics : public ClientOpPerformanceDataHandler
208 {
209 public:
210
211     virtual void handleClientOpPerformanceData (
212             const ClientOpPerformanceData & item)
213     {
214         // NOTE: We do not use this value so testing it is only a
215         // diagnostic function.
216         // FUTURE - Should test against operation we are expecting
217         if (!(0 <= item.operationType) || !(39 >= item.operationType) &&
218             _localVerboseTest)
219         {
220            cerr << "Error:Operation type out of expected range in"
221                         " ClientOpPerformanceData "
222                << endl;
223
224         }
225         returnedPerformanceData.operationType =  item.operationType;
226         if ((item.roundTripTime == 0) && _localVerboseTest)
227         {
228            cerr << "Error: roundTripTime incorrect (0) in"
229                    " ClientOpPerformanceData. "
230                << endl;
231         }
232         returnedPerformanceData.roundTripTime =  item.roundTripTime;
233
234         if ((item.requestSize == 0) && _localVerboseTest)
235         {
236             cerr << "Error:requestSize incorrect (0) in"
237                     " ClientOpPerformanceData "
238                 << endl;
239         }
240         returnedPerformanceData.requestSize =  item.requestSize;
241
242         if ((item.responseSize == 0) && _localVerboseTest)
243         {
244             cerr << "Error:responseSize incorrect (0)"
245                     " in ClientOpPerformanceData "
246                 << endl;
247         }
248         returnedPerformanceData.responseSize =  item.responseSize;
249
250         if (item.serverTimeKnown)
251         {
252             /* Bypass this because we are getting server times zero
253             if (item.serverTime == 0)
254             {
255                 cerr << "serverTime is incorrect in ClientOpPerformanceData "
256                     << endl;
257             }
258             */
259             returnedPerformanceData.serverTime =  item.serverTime;
260             returnedPerformanceData.serverTimeKnown =  item.serverTimeKnown;
261             returnedPerformanceData.roundTripTime =  item.roundTripTime;
262         }
263    }
264 };
265
266 ///////////////////////////////////////////////////////////////////////
267 //
268 //            Main
269 //
270 ///////////////////////////////////////////////////////////////////////
271
272 int main(int argc, char** argv)
273 {
274     //****** Show the args diagnostic display *******
275     // This is developer tool to sort out issues of incoming parameters
276     // Activated by making the last argument the keyword "displaycliargs".
277     // It displays all args and then eliminates argv[argc] so the proces
278     // can continue
279     if (strcmp(argv[argc - 1],"displaycliargs") == 0)
280     {
281         cout << "argc = " << --argc << endl;
282         for (int i = 0; i < argc; i++)
283         {
284             cout << "argv[" << i << "] = " << argv[i] << endl;
285         }
286     }
287
288 #ifdef PEGASUS_OS_ZOS
289     // for z/OS set stdout and stderr to EBCDIC
290     setEBCDICEncoding(STDOUT_FILENO);
291     setEBCDICEncoding(STDERR_FILENO);
292 #endif
293
294 #ifdef PEGASUS_OS_PASE
295     // Allow user group name larger than 8 chars in PASE environemnt
296     setenv("PASE_USRGRP_LIMITED","N",1);
297 #endif
298
299     // If no arguments, simply print usage message and terminate.
300     MessageLoader::_useProcessLocale = true;
301
302     if (argc == 1)
303     {
304         showUsage();
305         exit(0);
306     }
307
308     // Get options (from command line and from configuration file); this
309     // removes corresponding options and their arguments from the command
310     // line.
311
312     OptionManager om;
313
314     // Define the options structure. Common structure used for all action
315     // functions.
316     Options opts;
317
318     // Execute the following in a try block since there are several
319     // possibilities of exception and we want to separate these very basic
320     // exceptions from the action function exceptions. Exceptions in this
321     // block are probably due to programming errors or very strange things
322     // in input.
323     try
324     {
325         // Set the path for the config file.
326         //assume that the config file is local to directory where called.
327
328         String testHome = ".";
329         om.setMessagePath("pegasus/pegasusCLI");
330
331         // Build the options table based on the options defined in the
332         // function, a configuration file if it exists, and the command
333         // line input of options.
334         BuildOptionsTable(om, argc, argv, testHome);
335
336         // Parse and validate input Options based on the options table
337         CheckCommonOptionValues(om, argv, opts);
338
339         // move any other input parameters left to the valueParams List
340         //
341         /* FUTURE: note that this is in too limited since it assumes a fixed
342            number of parameters will be used for all of the commands
343            It should be expanded to allow for a variable minimum
344            number of commands before it picks up any extras.
345         */
346         if (argc > 2)
347         {
348             for (int i = 2 ; i < argc ; i++ )
349             {
350                     opts.valueParams.append(argv[i]);
351             }
352         }
353     }
354     catch(CIMException& e)
355     {
356         cerr << argv[0] << " Caught CIMException during init: "
357              << "\n" << e.getMessage()
358              << endl;
359         exit(e.getCode());
360     }
361
362     catch (Exception& e)
363     {
364         cerr << argv[0] << ": Caught Exception during init. "
365              << e.getMessage() << endl;
366         exit(CIMCLI_RTN_CODE_PEGASUS_EXCEPTION);
367     }
368     catch(...)
369     {
370         cerr << argv[0] << " Caught General Exception During Init:" << endl;
371         exit(GENERAL_CLI_ERROR_CODE);
372     }
373
374     // if there is an arg1, assume it is the command name.
375
376     if (argc > 1)
377     {
378         opts.cimCmd = argv[1];
379     }
380     else
381     {
382         cerr << "Error: P[eration name must be first or --c parameter."
383             << " \n  ex. cli enumerateclasses\n"
384             << "Enter " << argv[0] << " -h for help."
385             << endl;
386         exit(CIMCLI_INPUT_ERR);
387     }
388
389     // if the trace option was set initialize the trace function.
390     // fir cimcli
391     if (opts.trace != 0)
392     {
393         const char* tmpDir = getenv ("PEGASUS_TMP");
394             if (tmpDir == NULL)
395             {
396                 tmpDir = ".";
397             }
398             String traceFile (tmpDir);
399             traceFile.append("/cliTrace.trc");
400             Tracer::setTraceFile (traceFile.getCString());
401             Tracer::setTraceComponents("ALL");
402             Tracer::setTraceLevel(opts.trace);
403     }
404
405     if (opts.verboseTest && opts.debug)
406     {
407         cout << "Command = " << opts.cimCmd << endl;
408     }
409
410     // Find the command or the shortcut name input.
411
412     Operations thisOperation;
413
414     if (!thisOperation.find(opts.cimCmd))
415     {
416         cerr << "Error: Invalid cimcli operation name. "
417                 "Operation name must be first parmeter"
418                 " or --c parameter."
419             << " \n  ex. cli enumerateclasses\n"
420             << "Enter " << argv[0] << " -h for help."
421             << endl;
422         exit(GENERAL_CLI_ERROR_CODE);
423     }
424
425     // Start the time for total elapsed time for the command
426     Stopwatch totalElapsedExecutionTime;
427     totalElapsedExecutionTime.start();
428
429     //
430     // Try to open the connection to the cim server
431     //
432
433     try
434     {
435         if (thisOperation.get().ID_Operation != ID_ShowOptions)
436         {
437             String host;
438             HostLocator addr;
439
440             if (opts.location != String::EMPTY)
441             {
442                 addr.setHostLocator(opts.location);
443                 if (!addr.isValid())
444                 {
445                     throw InvalidLocatorException(opts.location);
446                 }
447                 host = addr.getHost();
448             }
449
450             Uint32 portNumber = System::lookupPort( WBEM_HTTP_SERVICE_NAME,
451                               WBEM_DEFAULT_HTTP_PORT );
452
453             // Set up SSL port and flag for verbose display
454             // if SSL included in build
455             String useSSL;
456 #ifdef PEGASUS_HAS_SSL
457             if (opts.ssl)
458             {
459                 portNumber = System::lookupPort( WBEM_HTTPS_SERVICE_NAME,
460                               WBEM_DEFAULT_HTTPS_PORT );
461             }
462             useSSL = " ssl=";
463             useSSL.append((opts.ssl)? "true" : "false");
464 #endif
465
466             if (host != String::EMPTY && addr.isPortSpecified())
467             {
468                 portNumber = addr.getPort();
469             }
470
471             //check whether we should use connect() or connectLocal()
472             //an empty location option indicates to use connectLocal()
473             if (String::equal(host, String::EMPTY))
474             {
475                 if (opts.verboseTest)
476                 {
477                     cout << "Connect with connectLocal" << endl;
478                 }
479                 opts.client.connectLocal();
480             }
481             else
482             {
483                 if (opts.verboseTest)
484                 {
485                     cout << "Connect to " << host
486                         << " port=" << portNumber
487                         << useSSL
488                          << " for User=" << opts.user
489                          << endl;
490                 }
491
492                 // Connect with SSL api only if SSL compile enabled
493 #ifdef PEGASUS_HAS_SSL
494                 String sslRndFilePath = "sss.rnd";
495                 if (opts.ssl) //connect over HTTPS
496                 {
497                     if (!String::equal(opts.clientCert, String::EMPTY)
498                             && !String::equal(opts.clientKey, String::EMPTY))
499                     {
500                         if (opts.verboseTest)
501                         {
502                             cout << "SSL options "
503                                 << "CertPath = " << opts.clientCert
504                                 << "clientKeyPath = "
505                                 << opts.clientKey << endl;
506                         }
507                         opts.client.connect(host,
508                                        portNumber,
509                                        SSLContext("",
510                                            opts.clientCert,
511                                            opts.clientKey,
512                                            NULL, sslRndFilePath),
513                                        opts.user,
514                                        opts.password);
515                     } else
516                     {
517                         opts.client.connect(host,
518                                        portNumber,
519                                        SSLContext("", NULL, sslRndFilePath),
520                                        opts.user,
521                                        opts.password);
522                     }
523                 } else //connect over HTTP
524                 {
525                     opts.client.connect(host, portNumber, opts.user,
526                                         opts.password);
527                 }
528 #else   // Not SSL
529                 opts.client.connect(host, portNumber, opts.user,
530                                     opts.password);
531 #endif
532             }
533         }  // end if if not show options.
534     }
535     catch(Exception &e)
536     {
537         cerr << "Pegasus Exception: " << e.getMessage() <<
538               " Trying to connect to " << opts.location << endl;
539         exit(CIMCLI_CONNECTION_FAILED);
540     }
541
542     // Register for Client statistics which might be returned with
543     // the response
544     ClientStatistics statistics = ClientStatistics();
545     _localVerboseTest = opts.verboseTest;
546     opts.client.registerClientOpPerformanceDataHandler(statistics);
547
548     // if delay option set, execute this delay between the connect and the
549     // execution of the command.
550     // NOTE: This was a test option for some specific tests
551     // FUTURE: Consider removing this option.
552     if (opts.delay != 0)
553     {
554         Threads::sleep(opts.delay * 1000);
555     }
556
557     // If the timeout is not zero, set the timeout for this connection.
558     if (opts.connectionTimeout != 0)
559     {
560         opts.client.setTimeout(opts.connectionTimeout * 1000);
561     }
562
563     // Save the total connect time.
564     double totalConnectTime = opts.elapsedTime.getElapsed();
565
566     // Setup the other timers.
567     double totalTime = 0;
568     Uint32 repeatCount = opts.repeat;
569     double maxTime = 0;
570     double minTime = 10000000;
571
572     Uint64 serverTotalTime = 0;
573     Uint64 maxServerTime = 0;
574     Uint64 minServerTime = 10000000;
575
576     Uint64 rtTotalTime = 0;
577     Uint64 maxRtTime = 0;
578     Uint64 minRtTime = 10000000;
579
580     //
581     //  Process the requestd operation action function
582     //  Process the function within a try block to catch all operation
583     //  command exceptions
584     //
585     try
586     {
587         // Loop to repeat the command a number of times.
588         // while opts.repeat > 0
589         do
590         {
591             // or exit with error through default of case logic
592             switch(thisOperation.get().ID_Operation)
593             {
594                 case ID_EnumerateInstanceNames :
595                     if (!_getClassNameInput(argc, argv, opts, true))
596                     {
597                         exit(CIMCLI_INPUT_ERR);
598                     }
599                     opts.termCondition = enumerateInstanceNames(opts);
600                     break;
601
602                 case ID_EnumerateAllInstanceNames :
603                     if (!_getClassNameInput(argc, argv, opts, false))
604                     {
605                         exit(CIMCLI_INPUT_ERR);
606                     }
607                     opts.termCondition = enumerateAllInstanceNames(opts);
608                     break;
609
610                 case ID_EnumerateInstances :
611                     if (!_getClassNameInput(argc, argv, opts, true))
612                     {
613                         exit(CIMCLI_INPUT_ERR);
614                     }
615                     opts.termCondition = enumerateInstances(opts);
616                     break;
617                 case ID_GetInstance :
618                     if (!_getObjectNameInput(argc, argv, opts, true))
619                     {
620                         exit(CIMCLI_INPUT_ERR);
621                     }
622                     opts.termCondition = getInstance(opts);
623                     break;
624
625                 case ID_EnumerateClassNames :
626                     if (!_getClassNameInput(argc, argv, opts, false))
627                     {
628                         exit(CIMCLI_INPUT_ERR);
629                     }
630                     opts.termCondition = enumerateClassNames(opts);
631                     break;
632
633                 case ID_EnumerateClasses :
634                     if (!_getClassNameInput(argc, argv, opts, false))
635                     {
636                         exit(CIMCLI_INPUT_ERR);
637                     }
638                     opts.termCondition = enumerateClasses(opts);
639                     break;
640
641                 case ID_GetClass :
642                     if (!_getClassNameInput(argc, argv, opts, true))
643                     {
644                         exit(CIMCLI_INPUT_ERR);
645                     }
646                     opts.termCondition = getClass(opts);
647                     break;
648
649                 case ID_CreateInstance :
650                     if (!_getClassNameInput(argc, argv, opts, true))
651                     {
652                         exit(CIMCLI_INPUT_ERR);
653                     }
654                     opts.termCondition = createInstance(opts);
655                     break;
656
657                 case ID_TestInstance :
658                     if (!_getObjectNameInput(argc, argv, opts, true))
659                     {
660                         exit(CIMCLI_INPUT_ERR);
661                     }
662                     opts.termCondition = testInstance(opts);
663                     break;
664
665                 case ID_ModifyInstance :
666                     if (!_getObjectNameInput(argc, argv, opts, true))
667                     {
668                         exit(CIMCLI_INPUT_ERR);
669                     }
670                     opts.termCondition = modifyInstance(opts);
671                     break;
672
673                 case ID_DeleteInstance :
674                     if (!_getObjectNameInput(argc, argv, opts, true))
675                     {
676                         exit(CIMCLI_INPUT_ERR);
677                     }
678                     opts.termCondition = deleteInstance(opts);
679                     break;
680
681                 case ID_CreateClass :
682                     cerr << "CreateClass not implemented" << endl;
683                     exit(CIMCLI_INPUT_ERR);
684                     break;
685
686                 case ID_DeleteClass :
687                     if (!_getClassNameInput(argc, argv, opts, true))
688                     {
689                         exit(CIMCLI_INPUT_ERR);
690                     }
691                     opts.termCondition = deleteClass(opts);
692                     break;
693
694                 case ID_GetProperty :
695                     if (argc < 4)
696                     {
697                         cout << "Usage: cli getproperty <instancename>"
698                             "<propertyname> or"
699                             " cli getproperty <classname>"
700                             " <propertyname> <keypropert=value>*" << endl;
701                         exit(CIMCLI_INPUT_ERR);
702                     }
703
704                     if (!_getObjectNameInput(argc, argv, opts, true))
705                     {
706                         exit(CIMCLI_INPUT_ERR);
707                     }
708
709                     opts.propertyName = argv[3];
710                     opts.valueParams.remove(0);
711
712                     opts.termCondition = getProperty(opts);
713                     break;
714
715                 case ID_SetProperty :
716                     if (argc < 5)
717                     {
718                         cout <<
719                            "Usage: cli setproperty instancename propertyname"
720                                 " value "
721                            << endl;
722                     }
723                     setProperty(opts);
724                     break;
725
726                 case ID_EnumerateQualifiers :
727                     opts.termCondition = enumerateQualifiers(opts);
728                     break;
729
730                 case ID_SetQualifier :
731                     cerr << "SetQualifer not implemented" << endl;
732                     exit(CIMCLI_INPUT_ERR);
733                     break;
734
735                 case ID_GetQualifier :
736                     if (!_getQualifierNameInput(argc, argv, opts))
737                     {
738                         exit(CIMCLI_INPUT_ERR);
739                     }
740                     opts.termCondition = getQualifier(opts);
741                     break;
742
743                 case ID_DeleteQualifier :
744                     if (!_getQualifierNameInput(argc, argv, opts))
745                     {
746                         exit(CIMCLI_INPUT_ERR);
747                     }
748                     opts.termCondition = deleteQualifier(opts);
749                     break;
750
751                 case ID_References  :
752                     if (!_getObjectNameInput(argc, argv, opts, true))
753                     {
754                         exit(CIMCLI_INPUT_ERR);
755                     }
756                     opts.termCondition = references(opts);
757                     break;
758
759                 case ID_ReferenceNames :
760                     if (!_getObjectNameInput(argc, argv, opts, true))
761                     {
762                         exit(CIMCLI_INPUT_ERR);
763                     }
764                     opts.termCondition = referenceNames(opts);
765                     break;
766
767                 case ID_Associators :
768                     if (!_getObjectNameInput(argc, argv, opts, true))
769                     {
770                         exit(CIMCLI_INPUT_ERR);
771                     }
772                     opts.termCondition = associators(opts);
773                     break;
774
775                 case ID_AssociatorNames :
776                     if (!_getObjectNameInput(argc, argv, opts, true))
777                     {
778                         exit(CIMCLI_INPUT_ERR);
779                     }
780                     opts.termCondition = associatorNames(opts);
781                     break;
782
783                 case ID_EnumerateNamespaces :
784                     // Note that the following constants are fixed here.  We
785                     // should be getting them from the environment to assure
786                     // that others know that we are using them.
787                     //opts.className = PEGASUS_CLASSNAME_CIMNAMESPACE;
788
789                     if (argc > 2)
790                     {
791                         opts.nameSpace = argv[2];
792                         opts.inputObjectName = argv[2];
793                     }
794                     else
795                     {
796                         // set nameSpace to interop namespace name
797                         opts.nameSpace =
798                             PEGASUS_NAMESPACENAME_INTEROP.getString();
799                     }
800
801                     opts.termCondition = enumerateNamespaceNames(opts);
802                     break;
803
804                 case ID_InvokeMethod :
805                     if (argc < 4)
806                     {
807                         cerr << "Usage: InvokeMethod requires that object and"
808                             " method names be specified.\n"
809                             "Input parameters are optional and can be"
810                             " specified as additional parameters to"
811                             " this call. "
812                             "Enter each input parameter as name=value"
813                             " (no spaces around equal sign)."
814                             << endl;
815                         exit(CIMCLI_INPUT_ERR);
816                     }
817
818                     if (!_getObjectNameInput(argc, argv, opts, true))
819                     {
820                         exit(CIMCLI_INPUT_ERR);
821                     }
822
823                     opts.methodName = CIMName(argv[3]);
824                     // remove the method name argument
825                     opts.valueParams.remove(0);
826
827                     // If there are any extra arguments they must be parameters
828                     // These parameters  can be used in addtion to parameters
829                     // ifrom the -ip option setting. Parameters found here must
830                     // be key=value pairs or they will generate an exception.
831
832                     opts.termCondition = invokeMethod(opts);
833                     break;
834
835                 case ID_ShowOptions :
836                     showUsage();
837                     break;
838
839                 case ID_ExecQuery:
840                     if (argc <= 2 && opts.query.size() == 0)
841                     {
842                         cerr << "ERROR: ExecQuery requires a query"
843                                 "filter definition\n"
844                                 "   - supplied directly as a parameter\n"
845                                 "   - OR supplied with the -f option\n"
846                                 "   The filterLanguage may be supplied\n"
847                                 "   - as the second argument\n"
848                                 "   - OR as the -ql option\n"
849                               << endl;
850                     }
851                     opts.query = argv[2];
852                     if (argc==4)
853                     {
854                         opts.queryLanguage = argv[3];
855                     }
856                     opts.termCondition = execQuery(opts);
857                     break;
858
859                 case ID_StatisticsOn:
860                     Boolean rtndState;
861                     setObjectManagerStatistics(opts, true, rtndState);
862                     break;
863
864                 case ID_StatisticsOff:
865                     opts.termCondition = setObjectManagerStatistics(
866                         opts, false, rtndState);
867                     break;
868
869                 default:
870                     cout << "Invalid cimcli operation name. "
871                             "Operation name must be first parmeter"
872                             " or --c parameter."
873                         << " \n  ex. cli enumerateclasses\n"
874                         << "Enter " << argv[0] << " -h for help."
875                         << endl;
876                     exit(CIMCLI_INPUT_ERR);
877                     break;
878             } // switch statement
879
880             // If the repeat option set, do any interim time calculation
881             // and output and decrement the repeat count
882             if (opts.repeat > 0)
883             {
884                 if (opts.verboseTest)
885                 {
886                     cout << "Repetitition " << opts.repeat << endl;
887                 }
888                 opts.repeat--;
889
890                 if (opts.time)
891                 {
892                     totalTime += opts.saveElapsedTime;
893                     maxTime = LOCAL_MAX(maxTime, opts.saveElapsedTime);
894                     minTime = LOCAL_MIN(minTime, opts.saveElapsedTime);
895                     rtTotalTime += (returnedPerformanceData.roundTripTime);
896                     maxRtTime = LOCAL_MAX(maxRtTime,
897                             returnedPerformanceData.roundTripTime);
898                     minRtTime = LOCAL_MIN(minRtTime,
899                             returnedPerformanceData.roundTripTime);
900
901                     if (returnedPerformanceData.serverTimeKnown)
902                     {
903                         serverTotalTime += (returnedPerformanceData.serverTime);
904                         maxServerTime = LOCAL_MAX(maxServerTime,
905                                 returnedPerformanceData.serverTime);
906                         minServerTime = LOCAL_MIN(minServerTime,
907                                 returnedPerformanceData.serverTime);
908                     }
909                 }
910             }
911         } while (opts.repeat > 0  );
912
913         // Command processing complete.  If the time parameter is set,
914         // output any total time information
915
916         if (opts.time)
917         {
918             cout << thisOperation.get().OperationName << " "
919                  << opts.inputObjectName;
920
921             if (repeatCount == 0)
922             {
923                 cout << " Time= "
924                     << opts.saveElapsedTime
925                     << " Sec "
926                     << " SvrTime= "
927                     << CIMValue(returnedPerformanceData.serverTime).toString()
928                     << " us "
929                     << " RtTime= "
930                     << CIMValue(returnedPerformanceData.roundTripTime).
931                            toString()
932                     << " us "
933                     << "Req size= "
934                     << CIMValue(returnedPerformanceData.requestSize).toString()
935                     << " b Resp size= "
936                     << CIMValue(returnedPerformanceData.responseSize).toString()
937                     << " b"
938                     << endl;
939             }
940             else
941             {
942                 cout << " Total Time "
943                     << totalTime
944                     << " for "
945                     << repeatCount
946                     << " ops. Avg= "
947                     << (totalTime * 1000000)/repeatCount
948                     << " us min= "
949                     << minTime * 1000000
950                     << " us max= "
951                     << (maxTime * 1000000)
952                     << " us SvrTime avg= "
953                     << CIMValue(serverTotalTime/repeatCount).toString()
954                     << " us SvrTime min= "
955                     << CIMValue(minServerTime).toString()
956                     << " us SvrTime max= "
957                     << CIMValue(maxServerTime).toString()
958                     << " us"
959                     << " RtTime avg= "
960                     << CIMValue(rtTotalTime/repeatCount).toString()
961                     << " us RtTime min= "
962                     << CIMValue(minRtTime).toString()
963                     << " us RtTime max= "
964                     << CIMValue(maxRtTime).toString()
965                     << " us"
966                     << endl;
967             }
968         }
969     }
970
971     // Exceptions for action operations try block
972     // The following exceptions are all routed to cerr
973     catch(CIMException& e)
974     {
975         cerr << argv[0] << " CIMException: "
976              <<" Cmd= " << opts.cimCmd
977              << " Object= " << opts.inputObjectName
978              << " Code= " << e.getCode()
979              << "\n" << e.getMessage()
980              << endl;
981         opts.termCondition = e.getCode();
982     }
983     catch(Exception& e)
984     {
985         cerr << argv[0] << " Pegasus Exception: " << e.getMessage()
986                 <<  ". Cmd = " << opts.cimCmd
987                 << " Object = " << opts.inputObjectName
988                 << endl;
989             opts.termCondition = CIMCLI_RTN_CODE_PEGASUS_EXCEPTION;
990     }
991     catch(...)
992     {
993         cerr << argv[0] << " Caught General Exception:" << endl;
994         opts.termCondition = CIMCLI_RTN_CODE_UNKNOWN_EXCEPTION;
995     }
996
997     totalElapsedExecutionTime.stop();
998
999     if (opts.time)
1000     {
1001         // if abnormal term, dump all times
1002         if (opts.termCondition != 0)
1003         {
1004             cout << "Exception" << endl;
1005             cout << "Prev Time " << opts.saveElapsedTime << " Sec" << endl;
1006             opts.saveElapsedTime = opts.elapsedTime.getElapsed();
1007             cout << "Last Time " << opts.saveElapsedTime << " Sec" << endl;
1008             cout << "Total Time " << totalTime << " for "
1009                 << repeatCount << " operations. Avg.= "
1010                 << totalTime/repeatCount
1011                 << " min= " << minTime << " max= " << maxTime << endl;
1012         }
1013
1014         cout << "Total Elapsed Time= "
1015              << totalElapsedExecutionTime.getElapsed()
1016              << " Sec. Terminated at " << System::getCurrentASCIITime()
1017              << endl;
1018     }
1019
1020     // if delay parameter set, sleep before terminating.
1021     if (opts.delay != 0)
1022     {
1023         Threads::sleep(opts.delay * 1000);
1024     }
1025
1026     // Terminate with termination code
1027
1028     exit(opts.termCondition);
1029 }
1030
1031 //PEGASUS_NAMESPACE_END
1032
1033 // END_OF_FILE