1 h.sterling 1.1 //%2005////////////////////////////////////////////////////////////////////////
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 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
19 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
20 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22 h.sterling 1.1 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Diane Olson (dianeols@us.ibm.com)
31 //
32 // Modified By: Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
33 //
34 // Modified By: Dave Rosckes (rosckes@us.ibm.com)
35 //
36 // Modified By: Bert Rivero (hurivero@us.ibm.com)
37 //
38 //
39 //%/////////////////////////////////////////////////////////////////////////////
40
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 h.sterling 1.1 #include <fcntl.h>
44 #include <unistd.h>
|
45 chuck 1.3 #include <sys/wait.h>
|
46 h.sterling 1.1 #include <Pegasus/Common/Config.h>
47 #include <Pegasus/Common/String.h>
48 #include <Pegasus/Common/Logger.h>
|
49 chuck 1.3 #include <Pegasus/Config/ConfigManager.h>
|
50 h.sterling 1.1 #include "OS400ConvertChar.h"
|
51 chuck 1.3 #include "SSLWrapperOS400.h"
52 #include "OS400SystemState.h"
|
53 lucier 1.4 #include "CIMRepositoryUpdate400.h" // upgrade utility
|
54 h.sterling 1.1 #include <Pegasus/Common/MessageLoader.h> //l10n
55 #include <except.h>
56
57 #include <stdio.h>
58 #include "qycmutiltyUtility.H"
59 #include "qycmjobjobJob.H"
60 #include "qycmmsgclsMessage.H"
61 #include "licall.h" // EPTCALL macros.
62
63 // Needed for QWTCHGJB API
64 #include <qwtchgjb.cleinc>
65 #include "qushdler.H"
66
67 //Needed for SQL APIs
68 #include "sqlcli.h"
69
70 // Structure need for the CHGJOB(QWTCHGJB) API
71 typedef struct jobChangeInfo
72 {
73 Qus_Job_Change_Information_t fieldNum;
74 Qus_JOBC0100_t format;
75 h.sterling 1.1 char data[31];
76 } jobChangeInfo_t;
77
78 // Errorcode for system API calls
79 Qus_EC_t errorCode;
80
81 PEGASUS_USING_PEGASUS;
82 PEGASUS_USING_STD;
83
84
85 //constructor
86 ServerProcess::ServerProcess() {}
87
88 //destructor
89 ServerProcess::~ServerProcess() {}
90
91 // no-ops
92 void ServerProcess::notify_parent(int id) {}
93 void ServerProcess::cimserver_set_process(void* p) {}
94 long ServerProcess::get_server_pid(void) { return 0; }
|
95 h.sterling 1.2 void ServerProcess::set_parent_pid(int pid) {}
|
96 h.sterling 1.1 int ServerProcess::get_proc(int pid) { return 0; }
97 int ServerProcess::cimserver_wait(void) { return 1; }
98 String ServerProcess::getHome(void) { return String::EMPTY; }
99
100 ///////////////////////////////////////////////////////////////////////
101 // cimserver_fork()
102 //
103 // The iSeries qycmctlcimCimomServer.C (QYCMCTLCIM program) code has
104 // already checked that the CIMOM server is not already running prior
105 // to calling the CIMOM server (QYCMCIMOM) and telling it to start itself.
106 // Therefore, no check is made in this method to ensure the CIMOM server
107 // is not already running.
108 //
109 // Note: This code was written because fork( ) is not supported on OS/400.
110 ///////////////////////////////////////////////////////////////////////
111 int ServerProcess::cimserver_fork(void)
112 {
|
113 lucier 1.4 // First migrate the server configuration settings into the planned file.
114 CIMRepositoryUpdate400 obj;
115 obj.preserveConfigSettings();
116
|
117 lucier 1.5 // TODO: This is here for now until we can move it into initialize. Right now it doesn't run because qycmsetupr won't work in a multi-threaded environment. See issue #AD2
118 obj.doIt();
119
|
120 h.sterling 1.1 #pragma convert(37)
121 char rc5[3] = "05"; // rc5 means the CIMOM Server failed to start
122 char cppServ[10] = "QYCMCIMOM";
123 ycmJob cppJob(YCMJOB_SRVNAME_10, YCMJOB_SRVUSER_10);
124
125 // Submit the server job (QYCMCIMOM). The job is submitted with the
126 // daemon=false parameter to avoid an infinite loop of jobs being
127 // submitted by this code!
128 if (YCMJOB_SUBMIT_FAILED == cppJob.submit(YCMJOB_SRVR_PGM,
129 YCMJOB_QSYS_LIB,
130 "daemon=false",
131 YCMJOB_JOBD,
132 YCMJOB_QSYS_LIB,
133 YCMJOB_CCSID_37,
134 YCMJOB_THREAD_YES))
135 { // QYCMCIMOM Server Failed on Submit Job
136 #pragma convert(0)
137
138 //l10n
139 //Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
140 //"cimserver_os400::cimserver_fork() - SBMJOB failed to start the QYCMCIMOM server program!!");
141 h.sterling 1.1 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
142 "src.Server.cimserver_os400.FAILED_TO_START_SERVER",
143 "$0 failed to start the $1 server program!!",
144 "cimserver_os400::cimserver_fork() - SBMJOB",
145 "QYCMCIMOM");
146
147
148 char chData[sizeof(rc5)+sizeof(cppServ)];
149 strcpy((char *)&chData,rc5);
150 strcat(chData,cppServ);
151
152 #pragma convert(37)
153 ycmMessage message("CPDDF80",
154 chData,
155 strlen(chData),
156 "cimserver_os400::cimserver_fork()",
157 ycmCTLCIMID,
158 utf8);
159 message.joblogIt(UserError,ycmMessage::Diagnostic);
160 #pragma convert(0)
161
162 h.sterling 1.1 // save the job log
163 system ("QSYS/CHGJOB JOB(*) LOG(4 00 *SECLVL)");
164
165
166 return(-1); // -1 indicates to QYCMCIMOM that the server failed to start
167 }
168
169 // The QYCMCIMOM job was submitted with daemon=false. This job can now exit.
170 // This is similiar to what the unix version of this code does - the parent exits
171 // after the fork( )
172 return(0);
173 }
174
175
176 ////////////////////////////////////////////////////
177 // CancelHandler
178 ////////////////////////////////////////////////////
179 void CancelHandler (_CNL_Hndlr_Parms_T *cancelParms)
180 { // make sure a job log gets saved too
181 system ("QSYS/CHGJOB JOB(*) LOG(4 00 *SECLVL)");
182 }
183 h.sterling 1.1
184
185 ////////////////////////////////////////////////////
186 // iSeries-specific function to initialize the server.
187 // Does the following:
188 // -- Sets the server type to QIBM_CIMOM
189 // so that iNavigator can start/stop it.
190 // -- Swaps the job user to QSYS.
191 // -- Changes the authority of QYCMJOBD
|
192 lucier 1.5 // -- Calls the upgrade utility
|
193 h.sterling 1.1 ////////////////////////////////////////////////////
194 int ServerProcess::cimserver_initialize(void)
195 {
196 SQLHENV henv; // SQL environment variable
197 long attr; // SQL attribute to be set
198
199 // setup cancel handler to make sure job log gets saved if we exit abnormally
200 // TODO: this is currently commented out because it causes build errors -
201 // it compiles just fine though. Hopefully this problem will be fixed
202 // (it's a known problem) and we can uncomment this #pragma.
203 // #pragma cancel_handler (CancelHandler, NULL)
204 try {
205 system ("QSYS/CHGJOB JOB(*) LOG(4 00 *SECLVL)");
206
207 #pragma convert(37)
208 //////////////////////////////////////////
209 // Change Job API call
210 // Change the server type to QICM_CIMOM
211 //////////////////////////////////////////
212 jobChangeInfo_t chg = {1,
213 46,
214 h.sterling 1.1 1911,
215 'C',
216 0X40,0X40,0X40,30,
217 "QIBM_CIMOM ",
218 };
219
220 // Initialize the error code structure to signal exceptions
221 errorCode.Bytes_Provided = 0;
222
223 // Call CHGJOB API with Server Type field
224 EPTCALL(QWTCHGJB, ("* ",
225 " ",
226 "JOBC0200",
227 &chg,
228 &errorCode), OFF, OFF);
229 #pragma convert(0)
230
231 ////////////////////////////////////////////////////
232 // Change authority to the qypsjobd job description
233 ////////////////////////////////////////////////////
234 system("QSYS/GRTOBJAUT OBJ(QSYS/QYCMJOBD) OBJTYPE(*JOBD) USER(*PUBLIC) AUT(*EXCLUDE)");
235 h.sterling 1.1
236 SQLAllocEnv(&henv); // Allocating SQL environment variable
237 attr = SQL_TRUE; // Set SQL attribute to true
238
239 // Set the SQL server mode to true.
240 // This will allow multiple connections to the same data source.
241 SQLSetEnvAttr(henv,SQL_ATTR_SERVER_MODE, &attr,0);
|
242 chuck 1.3
243 //--------------------------------------------------
244 // Create server SSL certificate and private key
245 // if they do not already exist.
246 //--------------------------------------------------
247
248 // Check if SSL is enabled on either the wbem-https or
249 // wbem-exp-https ports.
250 ConfigManager * configManager = ConfigManager::getInstance();
251 Boolean enableHttpsConnection = String::equal(
252 configManager->getCurrentValue("enableHttpsConnection"), "true");
253 Boolean enableSSLExportClientVerification = String::equal(
254 configManager->getCurrentValue("enableSSLExportClientVerification"), "true");
255 if (enableHttpsConnection || enableSSLExportClientVerification)
256 {
257 // Initialize the OS400 OpenSSL wrapper.
258 // This checks if the OpenSSL LPO is installed.
259 // It also activates the OpenSSL *SRVPGM and gets exports.
260 SSL_OS400_Init();
261
262 // Create the certificate if needed
263 chuck 1.3 // Get the location of the certificate
264 String certPath;
265 certPath = ConfigManager::getHomedPath(
266 configManager->getCurrentValue("sslCertificateFilePath"));
267
268 // Get the location of the private key
269 String keyPath;
270 keyPath = ConfigManager::getHomedPath(
271 configManager->getCurrentValue("sslKeyFilePath"));
272
273 SSL_CreateCert_OS400(keyPath, certPath);
274 }
275 }
276 catch (Exception & e)
277 {
278 //l10n
279 Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
280 e.getMessage());
281 return(-1);
282 }
|
283 h.sterling 1.1 catch (...)
284 {
285 //l10n
286 //Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
287 //"cimerver_os400::cimserver_os400_setup() - caught unknown exception\n");
288 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
289 "src.Server.cimserver_os400.CAUGHT_UNKNOWN_EXCEPTION",
290 "$0 caught unknown exception\n",
291 "cimerver_os400::cimserver_os400_setup() -");
292
293 return(-1);
294 }
|
295 lucier 1.4
|
296 lucier 1.5 // TODO: add this back in when we fix the problem with setupr not working in a multi-threaded environment.
|
297 lucier 1.4 // Call into the upgrade utility. This will perform any necessary upgrade step that need to be done. The upgrade program keys off of marker files which are created on install. This means that in most cases, nothing will be done unless the server is starting for the first time after an install.
|
298 lucier 1.5 // CIMRepositoryUpdate400 obj;
299 // obj.doIt();
|
300 h.sterling 1.1
301 // TODO: this is currently commented out because it causes build errors -
302 // it compiles just fine though. Hopefully this problem will be fixed
303 // (it's a known problem) and we can uncomment this #pragma.
304 // #pragma disable_handler
305
306 return(0);
307 }
308
309 ///////////////////////////////////////////////////////////////////////
310 // cimserver_kill()
311 //
312 // The iSeries qycmctlcimCimomServer.C (QYCMCTLCIM program) code has
313 // already checked that the CIMOM server is already running prior to
314 // calling the CIMOM server (QYCMCIMOM) and telling it to shutdown.
315 // However, a check is still made in this method because we have to
316 // find the job number in order to kill the job.
317 //
318 // For iSeries, this method is called regardless of whether we took
319 // errors trying to connect to the server - if the CIMOM server job
320 // is anywhere on the system, in any state, this method will find it
321 h.sterling 1.1 // and kill it dead!!
322 //
323 // NEVER call this method unless the server is unable to be shut down
324 // gracefully.
325 ///////////////////////////////////////////////////////////////////////
326 int ServerProcess::cimserver_kill(int id)
327 { // Need to kill the server
328 #pragma convert(37)
329 char rc2[3] = "02"; // CIMOM server failed to end
330 char cppServ[10] = "QYCMCIMOM";
331
332 // Construct a ycmJob object
333 ycmJob cppJob(YCMJOB_SRVNAME_10, YCMJOB_SRVUSER_10);
334 // Find the QYCMCIMOM job
335 char cppStatus = cppJob.find(YCMJOB_ALL_NUMBERS);
336
337 if (cppStatus == YCMJOB_FOUND) // CIMOM Server is Running
338 {
339 if (cppJob.end((char *)cppJob.getNumber().c_str(), 'C', 30) == YCMJOB_END_FAILED)
340 {
341
342 h.sterling 1.1 char chData[sizeof(rc2)+sizeof(cppServ)];
343 strcpy((char *)&chData,rc2);
344 strcat(chData,cppServ);
345
346 ycmMessage message("CPDDF81",
347 chData,
348 strlen(chData),
349 "cimserver_os400::cimserver_kill()",
350 ycmCTLCIMID,
351 utf8);
352 message.joblogIt(UserError,ycmMessage::Diagnostic);
353
354 #pragma convert(0)
355
356 //l10n
357 //Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
358 //"cimserver_os400::cimserver_kill - FAILED to end the QYCMCIMOM job!!");
359 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
360 "src.Server.cimserver_os400.FAILED_TO_END_JOB",
361 "$0 FAILED to end the $1 job!!",
362 "cimserver_os400::cimserver_kill -",
363 h.sterling 1.1 "QYCMCIMOM");
364
365
366 return -1; // Note: this return code is ignored by the CIMOM server.
367 }
368 }
369 // The case of the job not found is already handled in QYCMCTLCIM program
370 return(0);
371 }
372
373 ////////////////////////////////////////////////////
374 // Checks if the QYCMCIMOM server job is running.
375 ////////////////////////////////////////////////////
376 Boolean ServerProcess::isCIMServerRunning(void)
377 {
378 #pragma convert(37)
379 // Construct a ycmJob object
380 ycmJob cppJob(YCMJOB_SRVNAME_10, YCMJOB_SRVUSER_10);
381
382 // Find the QYCMCIMOM job
383 char cppStatus = cppJob.find(YCMJOB_ALL_NUMBERS);
384 h.sterling 1.1
385 if (cppStatus == YCMJOB_FOUND) // CIMOM Server is Running
386 {
387 return true;
388 }
389
390 return false;
391 #pragma convert(0)
392 }
393
394 ////////////////////////////////////////////////////
395 // Setup a fifo for process communication
396 ////////////////////////////////////////////////////
397 int init_fifo(const char * fifo_name){
398 int fifo = -1;
399 struct stat FIFO_STAT;
400
401 // Need to convert the fifo name to ebcdic because
402 // that is what stat and open want.
403 char tmp[256];
404 strcpy(tmp, fifo_name);
405 h.sterling 1.1 AtoE(tmp);
406
407 int stat_rc = stat( tmp, &FIFO_STAT );
408
409 // check if the FIFO already exists
410 if( S_ISFIFO( FIFO_STAT.st_mode ) ){
411 // prep FIFO, on this end we only want to write to it,
412 // set its I/O mode to not block on any reads
413 fifo = open(tmp, O_RDWR | O_NONBLOCK);
414 }
415 return fifo;
416 }
417
418
419 ////////////////////////////////////////////////////
420 // Sends return code back to caller before exiting...
421 ////////////////////////////////////////////////////
422 void ServerProcess::cimserver_exitRC(int rc){
423 int fifo = init_fifo(QYCMSSERV_FIFO);
424
425 if( fifo != -1 ){
426 h.sterling 1.1 char rc_tmp[3];
427 memset(rc_tmp, 0, 3);
428 sprintf(rc_tmp,"%d",rc);
429 AtoE(rc_tmp); // qycmctlcim wants ebcdic
430 write(fifo,rc_tmp,strlen(rc_tmp));
431 }
432
433 exit(rc);
434 }
435
436 ////////////////////////////////////////////////////
437 // Platform specific run
438 ////////////////////////////////////////////////////
439 int ServerProcess::platform_run( int argc, char** argv, Boolean shutdownOption )
440 {
441 return cimserver_run( argc, argv, shutdownOption );
442 }
443
|